Update V8 to r3121 as required for WebKit update.

Change-Id: Ic53e0aef9a9eb9b71ee7d25a8aef61520bba899c
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 9103403..f041041 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -67,7 +67,9 @@
     '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/test/cctest/cctest.status b/test/cctest/cctest.status
index 8fff769..b43cd64 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -33,6 +33,17 @@
 # BUG(382): Weird test. Can't guarantee that it never times out.
 test-api/ApplyInterruption: PASS || TIMEOUT
 
+# This is about to go away anyway since new snapshot code is on the way.
+test-serialize/Deserialize: FAIL
+test-serialize/DeserializeAndRunScript: FAIL
+test-serialize/DeserializeNatives: FAIL
+test-serialize/DeserializeExtensions: FAIL
+
+# These tests always fail.  They are here to test test.py.  If
+# they don't fail then test.py has failed.
+test-serialize/TestThatAlwaysFails: FAIL
+test-serialize/DependentTestThatAlwaysFails: FAIL
+
 
 [ $arch == arm ]
 
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index f430cbd..a943f30 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -25,7 +25,7 @@
 // (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 <limits.h>
 
 #include "v8.h"
 
@@ -35,6 +35,7 @@
 #include "snapshot.h"
 #include "platform.h"
 #include "top.h"
+#include "utils.h"
 #include "cctest.h"
 
 static bool IsNaN(double x) {
@@ -574,6 +575,44 @@
 }
 
 
+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 +741,88 @@
 }
 
 
+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 +1467,44 @@
 }
 
 
+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 +1969,7 @@
   // 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());
@@ -7883,6 +8042,333 @@
 }
 
 
+template <class ExternalArrayClass, class ElementType>
+static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
+                                    int64_t low,
+                                    int64_t high) {
+  v8::HandleScope scope;
+  LocalContext context;
+  const int kElementCount = 40;
+  int element_size = 0;
+  switch (array_type) {
+    case v8::kExternalByteArray:
+    case v8::kExternalUnsignedByteArray:
+      element_size = 1;
+      break;
+    case v8::kExternalShortArray:
+    case v8::kExternalUnsignedShortArray:
+      element_size = 2;
+      break;
+    case v8::kExternalIntArray:
+    case v8::kExternalUnsignedIntArray:
+    case v8::kExternalFloatArray:
+      element_size = 4;
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  ElementType* array_data =
+      static_cast<ElementType*>(malloc(kElementCount * element_size));
+  i::Handle<ExternalArrayClass> array =
+      i::Handle<ExternalArrayClass>::cast(
+          i::Factory::NewExternalArray(kElementCount, array_type, array_data));
+  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  for (int i = 0; i < kElementCount; i++) {
+    array->set(i, static_cast<ElementType>(i));
+  }
+  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  for (int i = 0; i < kElementCount; i++) {
+    CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get(i)));
+    CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
+  }
+
+  v8::Handle<v8::Object> obj = v8::Object::New();
+  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
+  // Set the elements to be the external array.
+  obj->SetIndexedPropertiesToExternalArrayData(array_data,
+                                               array_type,
+                                               kElementCount);
+  CHECK_EQ(1, static_cast<int>(jsobj->GetElement(1)->Number()));
+  obj->Set(v8_str("field"), v8::Int32::New(1503));
+  context->Global()->Set(v8_str("ext_array"), obj);
+  v8::Handle<v8::Value> result = CompileRun("ext_array.field");
+  CHECK_EQ(1503, result->Int32Value());
+  result = CompileRun("ext_array[1]");
+  CHECK_EQ(1, result->Int32Value());
+
+  // Check pass through of assigned smis
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += ext_array[i] = ext_array[i] = -i;"
+                      "}"
+                      "sum;");
+  CHECK_EQ(-28, result->Int32Value());
+
+  // Check assigned smis
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  ext_array[i] = i;"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
+
+  // Check assigned smis in reverse order
+  result = CompileRun("for (var i = 8; --i >= 0; ) {"
+                      "  ext_array[i] = i;"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
+
+  // Check pass through of assigned HeapNumbers
+  result = CompileRun("var sum = 0;"
+                      "for (var i = 0; i < 16; i+=2) {"
+                      "  sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
+                      "}"
+                      "sum;");
+  CHECK_EQ(-28, result->Int32Value());
+
+  // Check assigned HeapNumbers
+  result = CompileRun("for (var i = 0; i < 16; i+=2) {"
+                      "  ext_array[i] = (i * 0.5);"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 16; i+=2) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
+
+  // Check assigned HeapNumbers in reverse order
+  result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
+                      "  ext_array[i] = (i * 0.5);"
+                      "}"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 16; i+=2) {"
+                      "  sum += ext_array[i];"
+                      "}"
+                      "sum;");
+  CHECK_EQ(28, result->Int32Value());
+
+  i::ScopedVector<char> test_buf(1024);
+
+  // Check legal boundary conditions.
+  // The repeated loads and stores ensure the ICs are exercised.
+  const char* boundary_program =
+      "var res = 0;"
+      "for (var i = 0; i < 16; i++) {"
+      "  ext_array[i] = %lld;"
+      "  if (i > 8) {"
+      "    res = ext_array[i];"
+      "  }"
+      "}"
+      "res;";
+  i::OS::SNPrintF(test_buf,
+                  boundary_program,
+                  low);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(low, result->IntegerValue());
+
+  i::OS::SNPrintF(test_buf,
+                  boundary_program,
+                  high);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(high, result->IntegerValue());
+
+  // Check misprediction of type in IC.
+  result = CompileRun("var tmp_array = ext_array;"
+                      "var sum = 0;"
+                      "for (var i = 0; i < 8; i++) {"
+                      "  tmp_array[i] = i;"
+                      "  sum += tmp_array[i];"
+                      "  if (i == 4) {"
+                      "    tmp_array = {};"
+                      "  }"
+                      "}"
+                      "sum;");
+  i::Heap::CollectAllGarbage(false);  // Force GC to trigger verification.
+  CHECK_EQ(28, result->Int32Value());
+
+  // Make sure out-of-range loads do not throw.
+  i::OS::SNPrintF(test_buf,
+                  "var caught_exception = false;"
+                  "try {"
+                  "  ext_array[%d];"
+                  "} catch (e) {"
+                  "  caught_exception = true;"
+                  "}"
+                  "caught_exception;",
+                  kElementCount);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(false, result->BooleanValue());
+
+  // Make sure out-of-range stores do not throw.
+  i::OS::SNPrintF(test_buf,
+                  "var caught_exception = false;"
+                  "try {"
+                  "  ext_array[%d] = 1;"
+                  "} catch (e) {"
+                  "  caught_exception = true;"
+                  "}"
+                  "caught_exception;",
+                  kElementCount);
+  result = CompileRun(test_buf.start());
+  CHECK_EQ(false, result->BooleanValue());
+
+  // Check other boundary conditions, values and operations.
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  ext_array[7] = undefined;"
+                      "}"
+                      "ext_array[7];");
+  CHECK_EQ(0, result->Int32Value());
+  CHECK_EQ(0, static_cast<int>(jsobj->GetElement(7)->Number()));
+
+  result = CompileRun("for (var i = 0; i < 8; i++) {"
+                      "  ext_array[6] = '2.3';"
+                      "}"
+                      "ext_array[6];");
+  CHECK_EQ(2, result->Int32Value());
+  CHECK_EQ(2, static_cast<int>(jsobj->GetElement(6)->Number()));
+
+  if (array_type != v8::kExternalFloatArray) {
+    // Though the specification doesn't state it, be explicit about
+    // converting NaNs and +/-Infinity to zero.
+    result = CompileRun("for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = 5;"
+                        "}"
+                        "for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = NaN;"
+                        "}"
+                        "ext_array[5];");
+    CHECK_EQ(0, result->Int32Value());
+    CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
+
+    result = CompileRun("for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = 5;"
+                        "}"
+                        "for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = Infinity;"
+                        "}"
+                        "ext_array[5];");
+    CHECK_EQ(0, result->Int32Value());
+    CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
+
+    result = CompileRun("for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = 5;"
+                        "}"
+                        "for (var i = 0; i < 8; i++) {"
+                        "  ext_array[i] = -Infinity;"
+                        "}"
+                        "ext_array[5];");
+    CHECK_EQ(0, result->Int32Value());
+    CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value());
+  }
+
+  result = CompileRun("ext_array[3] = 33;"
+                      "delete ext_array[3];"
+                      "ext_array[3];");
+  CHECK_EQ(33, result->Int32Value());
+
+  result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
+                      "ext_array[2] = 12; ext_array[3] = 13;"
+                      "ext_array.__defineGetter__('2',"
+                      "function() { return 120; });"
+                      "ext_array[2];");
+  CHECK_EQ(12, result->Int32Value());
+
+  result = CompileRun("var js_array = new Array(40);"
+                      "js_array[0] = 77;"
+                      "js_array;");
+  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
+
+  result = CompileRun("ext_array[1] = 23;"
+                      "ext_array.__proto__ = [];"
+                      "js_array.__proto__ = ext_array;"
+                      "js_array.concat(ext_array);");
+  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
+  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
+
+  result = CompileRun("ext_array[1] = 23;");
+  CHECK_EQ(23, result->Int32Value());
+
+  free(array_data);
+}
+
+
+THREADED_TEST(ExternalByteArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalByteArray, int8_t>(
+      v8::kExternalByteArray,
+      -128,
+      127);
+}
+
+
+THREADED_TEST(ExternalUnsignedByteArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalUnsignedByteArray, uint8_t>(
+      v8::kExternalUnsignedByteArray,
+      0,
+      255);
+}
+
+
+THREADED_TEST(ExternalShortArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalShortArray, int16_t>(
+      v8::kExternalShortArray,
+      -32768,
+      32767);
+}
+
+
+THREADED_TEST(ExternalUnsignedShortArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalUnsignedShortArray, uint16_t>(
+      v8::kExternalUnsignedShortArray,
+      0,
+      65535);
+}
+
+
+THREADED_TEST(ExternalIntArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalIntArray, int32_t>(
+      v8::kExternalIntArray,
+      INT_MIN,   // -2147483648
+      INT_MAX);  //  2147483647
+}
+
+
+THREADED_TEST(ExternalUnsignedIntArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalUnsignedIntArray, uint32_t>(
+      v8::kExternalUnsignedIntArray,
+      0,
+      UINT_MAX);  // 4294967295
+}
+
+
+THREADED_TEST(ExternalFloatArray) {
+  ExternalArrayTestHelper<v8::internal::ExternalFloatArray, float>(
+      v8::kExternalFloatArray,
+      -500,
+      500);
+}
+
+
+THREADED_TEST(ExternalArrays) {
+  TestExternalByteArray();
+  TestExternalUnsignedByteArray();
+  TestExternalShortArray();
+  TestExternalUnsignedShortArray();
+  TestExternalIntArray();
+  TestExternalUnsignedIntArray();
+  TestExternalFloatArray();
+}
+
+
 THREADED_TEST(ScriptContextDependence) {
   v8::HandleScope scope;
   LocalContext c1;
@@ -7913,11 +8399,15 @@
 }
 
 
-// Test that idle notification can be handled when V8 has not yet been
-// set up.
+// Test that idle notification can be handled and eventually returns true.
 THREADED_TEST(IdleNotification) {
-  for (int i = 0; i < 100; i++) v8::V8::IdleNotification(true);
-  for (int i = 0; i < 100; i++) v8::V8::IdleNotification(false);
+  bool rv = false;
+  for (int i = 0; i < 100; i++) {
+    rv = v8::V8::IdleNotification();
+    if (rv)
+      break;
+  }
+  CHECK(rv == true);
 }
 
 
@@ -7993,3 +8483,15 @@
     CHECK(stack_limit == set_limit);
   }
 }
+
+
+THREADED_TEST(GetHeapStatistics) {
+  v8::HandleScope scope;
+  LocalContext c1;
+  v8::HeapStatistics heap_statistics;
+  CHECK_EQ(heap_statistics.total_heap_size(), 0);
+  CHECK_EQ(heap_statistics.used_heap_size(), 0);
+  v8::V8::GetHeapStatistics(&heap_statistics);
+  CHECK_NE(heap_statistics.total_heap_size(), 0);
+  CHECK_NE(heap_statistics.used_heap_size(), 0);
+}
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc
index cd750c5..81aa973 100644
--- a/test/cctest/test-assembler-x64.cc
+++ b/test/cctest/test-assembler-x64.cc
@@ -44,6 +44,7 @@
 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::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 @@
   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 @@
   // 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 @@
   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 @@
 
   // 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 @@
   // 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 @@
   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/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 1da363c..4ffcee3 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -3539,6 +3539,52 @@
 }
 
 
+// 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 @@
   // 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 @@
   if (IsBreakEventMessage(print_buffer)) {
     threaded_debugging_barriers.barrier_2.Wait();
   }
-  printf("%s\n", print_buffer);
-  fflush(stdout);
 }
 
 
@@ -3911,16 +3953,20 @@
 
 
 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 @@
   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 @@
       "\"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 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 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 @@
       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 @@
       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 @@
       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/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index af9fb97..74db234 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -363,7 +363,31 @@
     __ 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/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index eb32b65..9911ce4 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -132,15 +132,19 @@
   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 @@
   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/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 65ab50a..3983215 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -430,6 +430,50 @@
 #endif  // __linux__
 
 
+// Test for issue http://crbug.com/23768 in Chromium.
+// Heap can contain scripts with already disposed external sources.
+// We need to verify that LogCompiledFunctions doesn't crash on them.
+namespace {
+
+class SimpleExternalString : public v8::String::ExternalStringResource {
+ public:
+  explicit SimpleExternalString(const char* source)
+      : utf_source_(strlen(source)) {
+    for (int i = 0; i < utf_source_.length(); ++i)
+      utf_source_[i] = source[i];
+  }
+  virtual ~SimpleExternalString() {}
+  virtual size_t length() const { return utf_source_.length(); }
+  virtual const uint16_t* data() const { return utf_source_.start(); }
+ private:
+  i::ScopedVector<uint16_t> utf_source_;
+};
+
+}  // namespace
+
+TEST(Issue23768) {
+  v8::HandleScope scope;
+  v8::Handle<v8::Context> env = v8::Context::New();
+  env->Enter();
+
+  SimpleExternalString source_ext_str("(function ext() {})();");
+  v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
+  // Script needs to have a name in order to trigger InitLineEnds execution.
+  v8::Handle<v8::String> origin = v8::String::New("issue-23768-test");
+  v8::Handle<v8::Script> evil_script = v8::Script::Compile(source, origin);
+  CHECK(!evil_script.IsEmpty());
+  CHECK(!evil_script->Run().IsEmpty());
+  i::Handle<i::ExternalTwoByteString> i_source(
+      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
+  // This situation can happen if source was an external string disposed
+  // by its owner.
+  i_source->set_resource(NULL);
+
+  // Must not crash.
+  i::Logger::LogCompiledFunctions();
+}
+
+
 static inline bool IsStringEqualTo(const char* r, const char* s) {
   return strncmp(r, s, strlen(r)) == 0;
 }
diff --git a/test/cctest/test-macro-assembler-x64.cc b/test/cctest/test-macro-assembler-x64.cc
new file mode 100755
index 0000000..9c1197f
--- /dev/null
+++ b/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/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 743375d..e56f0f4 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -71,10 +71,6 @@
 
 
 TEST(Promotion) {
-  // Test the situation that some objects in new space are promoted to the
-  // old space
-  if (Snapshot::IsEnabled()) return;
-
   // Ensure that we get a compacting collection so that objects are promoted
   // from new space.
   FLAG_gc_global = true;
@@ -106,7 +102,6 @@
 
 
 TEST(NoPromotion) {
-  if (Snapshot::IsEnabled()) return;
   Heap::ConfigureHeap(2*256*KB, 4*MB);
 
   // Test the situation that some objects in new space are promoted to
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 6939a80..db37eb3 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -286,3 +286,22 @@
   v8::Local<v8::Value> value = script->Run();
   CHECK(value->IsUndefined());
 }
+
+
+extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
+
+
+TEST(TestThatAlwaysSucceeds) {
+}
+
+
+TEST(TestThatAlwaysFails) {
+  bool ArtificialFailure = false;
+  CHECK(ArtificialFailure);
+}
+
+
+DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
+  bool ArtificialFailure2 = false;
+  CHECK(ArtificialFailure2);
+}
diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc
index d946a7f..1a26883 100644
--- a/test/cctest/test-spaces.cc
+++ b/test/cctest/test-spaces.cc
@@ -99,9 +99,9 @@
 
 TEST(MemoryAllocator) {
   CHECK(Heap::ConfigureHeapDefault());
-  CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
+  CHECK(MemoryAllocator::Setup(Heap::MaxReserved()));
 
-  OldSpace faked_space(Heap::MaxCapacity(), OLD_POINTER_SPACE, NOT_EXECUTABLE);
+  OldSpace faked_space(Heap::MaxReserved(), OLD_POINTER_SPACE, NOT_EXECUTABLE);
   int total_pages = 0;
   int requested = 2;
   int allocated;
@@ -155,16 +155,16 @@
 
 TEST(NewSpace) {
   CHECK(Heap::ConfigureHeapDefault());
-  CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
+  CHECK(MemoryAllocator::Setup(Heap::MaxReserved()));
 
   NewSpace new_space;
 
   void* chunk =
-      MemoryAllocator::ReserveInitialChunk(2 * Heap::YoungGenerationSize());
+      MemoryAllocator::ReserveInitialChunk(4 * Heap::ReservedSemiSpaceSize());
   CHECK(chunk != NULL);
   Address start = RoundUp(static_cast<Address>(chunk),
-                          Heap::YoungGenerationSize());
-  CHECK(new_space.Setup(start, Heap::YoungGenerationSize()));
+                          2 * Heap::ReservedSemiSpaceSize());
+  CHECK(new_space.Setup(start, 2 * Heap::ReservedSemiSpaceSize()));
   CHECK(new_space.HasBeenSetup());
 
   while (new_space.Available() >= Page::kMaxHeapObjectSize) {
@@ -180,18 +180,18 @@
 
 TEST(OldSpace) {
   CHECK(Heap::ConfigureHeapDefault());
-  CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
+  CHECK(MemoryAllocator::Setup(Heap::MaxReserved()));
 
-  OldSpace* s = new OldSpace(Heap::OldGenerationSize(),
+  OldSpace* s = new OldSpace(Heap::MaxOldGenerationSize(),
                              OLD_POINTER_SPACE,
                              NOT_EXECUTABLE);
   CHECK(s != NULL);
 
   void* chunk =
-      MemoryAllocator::ReserveInitialChunk(2 * Heap::YoungGenerationSize());
+      MemoryAllocator::ReserveInitialChunk(4 * Heap::ReservedSemiSpaceSize());
   CHECK(chunk != NULL);
   Address start = static_cast<Address>(chunk);
-  size_t size = RoundUp(start, Heap::YoungGenerationSize()) - start;
+  size_t size = RoundUp(start, 2 * Heap::ReservedSemiSpaceSize()) - start;
 
   CHECK(s->Setup(start, size));