Update V8 to r4924 as required by WebKit r61871
Change-Id: Ic819dad0c1c9e035b8ffd306c96656ba87c5e85a
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 9123125..c426db4 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -27,8 +27,6 @@
#include <limits.h>
-#define USE_NEW_QUERY_CALLBACKS
-
#include "v8.h"
#include "api.h"
@@ -9637,6 +9635,45 @@
}
+THREADED_TEST(PixelArrayInfo) {
+ v8::HandleScope scope;
+ LocalContext context;
+ for (int size = 0; size < 100; size += 10) {
+ uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
+ v8::Handle<v8::Object> obj = v8::Object::New();
+ obj->SetIndexedPropertiesToPixelData(pixel_data, size);
+ CHECK(obj->HasIndexedPropertiesInPixelData());
+ CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
+ CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
+ free(pixel_data);
+ }
+}
+
+
+static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
+ switch (array_type) {
+ case v8::kExternalByteArray:
+ case v8::kExternalUnsignedByteArray:
+ return 1;
+ break;
+ case v8::kExternalShortArray:
+ case v8::kExternalUnsignedShortArray:
+ return 2;
+ break;
+ case v8::kExternalIntArray:
+ case v8::kExternalUnsignedIntArray:
+ case v8::kExternalFloatArray:
+ return 4;
+ break;
+ default:
+ UNREACHABLE();
+ return -1;
+ }
+ UNREACHABLE();
+ return -1;
+}
+
+
template <class ExternalArrayClass, class ElementType>
static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
int64_t low,
@@ -9644,25 +9681,7 @@
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;
- }
+ int element_size = ExternalArrayElementSize(array_type);
ElementType* array_data =
static_cast<ElementType*>(malloc(kElementCount * element_size));
i::Handle<ExternalArrayClass> array =
@@ -10043,6 +10062,35 @@
}
+void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
+ v8::HandleScope scope;
+ LocalContext context;
+ for (int size = 0; size < 100; size += 10) {
+ int element_size = ExternalArrayElementSize(array_type);
+ void* external_data = malloc(size * element_size);
+ v8::Handle<v8::Object> obj = v8::Object::New();
+ obj->SetIndexedPropertiesToExternalArrayData(
+ external_data, array_type, size);
+ CHECK(obj->HasIndexedPropertiesInExternalArrayData());
+ CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
+ CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
+ CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
+ free(external_data);
+ }
+}
+
+
+THREADED_TEST(ExternalArrayInfo) {
+ ExternalArrayInfoTestHelper(v8::kExternalByteArray);
+ ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
+ ExternalArrayInfoTestHelper(v8::kExternalShortArray);
+ ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
+ ExternalArrayInfoTestHelper(v8::kExternalIntArray);
+ ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
+ ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
+}
+
+
THREADED_TEST(ScriptContextDependence) {
v8::HandleScope scope;
LocalContext c1;
@@ -10127,7 +10175,13 @@
stackTrace->GetFrame(0));
checkStackFrame(origin, "baz", 8, 3, false, true,
stackTrace->GetFrame(1));
- checkStackFrame(NULL, "", 1, 1, true, false,
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ bool is_eval = true;
+#else // ENABLE_DEBUGGER_SUPPORT
+ bool is_eval = false;
+#endif // ENABLE_DEBUGGER_SUPPORT
+
+ checkStackFrame(NULL, "", 1, 1, is_eval, false,
stackTrace->GetFrame(2));
// The last frame is an anonymous function that has the initial call to foo.
checkStackFrame(origin, "", 10, 1, false, false,
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 4c3ff5e..e689637 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -25,9 +25,9 @@
// (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>
+#ifdef ENABLE_DEBUGGER_SUPPORT
-#define USE_NEW_QUERY_CALLBACKS
+#include <stdlib.h>
#include "v8.h"
@@ -194,8 +194,9 @@
static int break_point = 0;
Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
Debug::SetBreakPoint(
- shared, position,
- Handle<Object>(v8::internal::Smi::FromInt(++break_point)));
+ shared,
+ Handle<Object>(v8::internal::Smi::FromInt(++break_point)),
+ &position);
return break_point;
}
@@ -2029,6 +2030,51 @@
}
+// Test top level script break points set on lines.
+TEST(ScriptBreakPointLineTopLevel) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ env.ExposeDebug();
+
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+ v8::Undefined());
+
+ v8::Local<v8::String> script = v8::String::New(
+ "function f() {\n"
+ " a = 1; // line 1\n"
+ "}\n"
+ "a = 2; // line 3\n");
+ v8::Local<v8::Function> f;
+ {
+ v8::HandleScope scope;
+ v8::Script::Compile(script, v8::String::New("test.html"))->Run();
+ }
+ f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+ Heap::CollectAllGarbage(false);
+
+ SetScriptBreakPointByNameFromJS("test.html", 3, -1);
+
+ // Call f and check that there was no break points.
+ break_point_hit_count = 0;
+ f->Call(env->Global(), 0, NULL);
+ CHECK_EQ(0, break_point_hit_count);
+
+ // Recompile and run script and check that break point was hit.
+ break_point_hit_count = 0;
+ v8::Script::Compile(script, v8::String::New("test.html"))->Run();
+ CHECK_EQ(1, break_point_hit_count);
+
+ // Call f and check that there are still no break points.
+ break_point_hit_count = 0;
+ f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+ CHECK_EQ(0, break_point_hit_count);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
+
+
// Test that it is possible to remove the last break point for a function
// inside the break handling of that break point.
TEST(RemoveBreakPointInBreak) {
@@ -6571,3 +6617,4 @@
CheckDebuggerUnloaded();
}
+#endif // ENABLE_DEBUGGER_SUPPORT
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc
index c4be35e..7587da8 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -27,8 +27,6 @@
#include <stdlib.h>
-#define USE_NEW_QUERY_CALLBACKS
-
#include "v8.h"
#include "heap.h"
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index 3189e5e..5903fe6 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -248,6 +248,72 @@
COMPARE(mvn(r5, Operand(r4), SetCC, cc),
"31f05004 mvnccs r5, r4");
+ // Instructions autotransformed by the assembler.
+ // mov -> mvn.
+ COMPARE(mov(r3, Operand(-1), LeaveCC, al),
+ "e3e03000 mvn r3, #0");
+ COMPARE(mov(r4, Operand(-2), SetCC, al),
+ "e3f04001 mvns r4, #1");
+ COMPARE(mov(r5, Operand(0x0ffffff0), SetCC, ne),
+ "13f052ff mvnnes r5, #-268435441");
+ COMPARE(mov(r6, Operand(-1), LeaveCC, ne),
+ "13e06000 mvnne r6, #0");
+
+ // mvn -> mov.
+ COMPARE(mvn(r3, Operand(-1), LeaveCC, al),
+ "e3a03000 mov r3, #0");
+ COMPARE(mvn(r4, Operand(-2), SetCC, al),
+ "e3b04001 movs r4, #1");
+ COMPARE(mvn(r5, Operand(0x0ffffff0), SetCC, ne),
+ "13b052ff movnes r5, #-268435441");
+ COMPARE(mvn(r6, Operand(-1), LeaveCC, ne),
+ "13a06000 movne r6, #0");
+
+ // mov -> movw.
+ if (CpuFeatures::IsSupported(ARMv7)) {
+ COMPARE(mov(r5, Operand(0x01234), LeaveCC, ne),
+ "13015234 movwne r5, #4660");
+ // We only disassemble one instruction so the eor instruction is not here.
+ COMPARE(eor(r5, r4, Operand(0x1234), LeaveCC, ne),
+ "1301c234 movwne ip, #4660");
+ // Movw can't do setcc so we don't get that here. Mov immediate with setcc
+ // is pretty strange anyway.
+ COMPARE(mov(r5, Operand(0x01234), SetCC, ne),
+ "159fc000 ldrne ip, [pc, #+0]");
+ // We only disassemble one instruction so the eor instruction is not here.
+ // The eor does the setcc so we get a movw here.
+ COMPARE(eor(r5, r4, Operand(0x1234), SetCC, ne),
+ "1301c234 movwne ip, #4660");
+
+ COMPARE(movt(r5, 0x4321, ne),
+ "13445321 movtne r5, #17185");
+ COMPARE(movw(r5, 0xabcd, eq),
+ "030a5bcd movweq r5, #43981");
+ }
+
+ // Eor doesn't have an eor-negative variant, but we can do an mvn followed by
+ // an eor to get the same effect.
+ COMPARE(eor(r5, r4, Operand(0xffffff34), SetCC, ne),
+ "13e0c0cb mvnne ip, #203");
+
+ // and <-> bic.
+ COMPARE(and_(r3, r5, Operand(0xfc03ffff)),
+ "e3c537ff bic r3, r5, #66846720");
+ COMPARE(bic(r3, r5, Operand(0xfc03ffff)),
+ "e20537ff and r3, r5, #66846720");
+
+ // sub <-> add.
+ COMPARE(add(r3, r5, Operand(-1024)),
+ "e2453b01 sub r3, r5, #1024");
+ COMPARE(sub(r3, r5, Operand(-1024)),
+ "e2853b01 add r3, r5, #1024");
+
+ // cmp <-> cmn.
+ COMPARE(cmp(r3, Operand(-1024)),
+ "e3730b01 cmn r3, #1024");
+ COMPARE(cmn(r3, Operand(-1024)),
+ "e3530b01 cmp r3, #1024");
+
// Miscellaneous instructions encoded as type 0.
COMPARE(blx(ip),
"e12fff3c blx ip");
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index c8e0197..e51bfab 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -276,9 +276,11 @@
__ jmp(&L1);
__ jmp(Operand(ebx, ecx, times_4, 10000));
+#ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference after_break_target =
ExternalReference(Debug_Address::AfterBreakTarget());
__ jmp(Operand::StaticVariable(after_break_target));
+#endif // ENABLE_DEBUGGER_SUPPORT
__ jmp(ic, RelocInfo::CODE_TARGET);
__ nop();
@@ -375,7 +377,7 @@
__ divsd(xmm1, xmm0);
__ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
__ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
- __ comisd(xmm0, xmm1);
+ __ ucomisd(xmm0, xmm1);
// 128 bit move instructions.
__ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000));
diff --git a/test/cctest/test-func-name-inference.cc b/test/cctest/test-func-name-inference.cc
index 67791fb..563cc4b 100644
--- a/test/cctest/test-func-name-inference.cc
+++ b/test/cctest/test-func-name-inference.cc
@@ -81,6 +81,7 @@
int func_pos = Runtime::StringMatch(script_src, func_pos_str, 0);
CHECK_NE(0, func_pos);
+#ifdef ENABLE_DEBUGGER_SUPPORT
// Obtain SharedFunctionInfo for the function.
Object* shared_func_info_ptr =
Runtime::FindSharedFunctionInfoInScript(i_script, func_pos);
@@ -92,6 +93,7 @@
SmartPointer<char> inferred_name =
shared_func_info->inferred_name()->ToCString();
CHECK_EQ(ref_inferred_name, *inferred_name);
+#endif // ENABLE_DEBUGGER_SUPPORT
}
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 2e56894..7f1e3d8 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -6,9 +6,11 @@
#include "v8.h"
#include "heap-profiler.h"
+#include "snapshot.h"
#include "string-stream.h"
#include "cctest.h"
#include "zone-inl.h"
+#include "../include/v8-profiler.h"
namespace i = v8::internal;
using i::ClustersCoarser;
@@ -390,4 +392,236 @@
CHECK_EQ("(global property);1", printer.GetRetainers("C"));
}
+
+namespace {
+
+class NamedEntriesDetector {
+ public:
+ NamedEntriesDetector()
+ : has_A1(false), has_B1(false), has_C1(false),
+ has_A2(false), has_B2(false), has_C2(false) {
+ }
+
+ void Apply(i::HeapEntry* entry) {
+ const char* node_name = entry->name();
+ if (strcmp("A1", node_name) == 0
+ && entry->GetRetainingPaths()->length() > 0) has_A1 = true;
+ if (strcmp("B1", node_name) == 0
+ && entry->GetRetainingPaths()->length() > 0) has_B1 = true;
+ if (strcmp("C1", node_name) == 0
+ && entry->GetRetainingPaths()->length() > 0) has_C1 = true;
+ if (strcmp("A2", node_name) == 0
+ && entry->GetRetainingPaths()->length() > 0) has_A2 = true;
+ if (strcmp("B2", node_name) == 0
+ && entry->GetRetainingPaths()->length() > 0) has_B2 = true;
+ if (strcmp("C2", node_name) == 0
+ && entry->GetRetainingPaths()->length() > 0) has_C2 = true;
+ }
+
+ bool has_A1;
+ bool has_B1;
+ bool has_C1;
+ bool has_A2;
+ bool has_B2;
+ bool has_C2;
+};
+
+} // namespace
+
+
+static const v8::HeapGraphNode* GetGlobalObject(
+ const v8::HeapSnapshot* snapshot) {
+ CHECK_EQ(1, snapshot->GetHead()->GetChildrenCount());
+ return snapshot->GetHead()->GetChild(0)->GetToNode();
+}
+
+
+static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
+ v8::HeapGraphEdge::Type type,
+ const char* name) {
+ for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
+ const v8::HeapGraphEdge* prop = node->GetChild(i);
+ v8::String::AsciiValue prop_name(prop->GetName());
+ if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
+ return prop->GetToNode();
+ }
+ return NULL;
+}
+
+
+static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
+ for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
+ const v8::HeapGraphEdge* prop = node->GetChild(i);
+ const v8::HeapGraphNode* node = prop->GetToNode();
+ if (node->GetType() == v8::HeapGraphNode::STRING) {
+ v8::String::AsciiValue node_name(node->GetName());
+ if (strcmp(contents, *node_name) == 0) return true;
+ }
+ }
+ return false;
+}
+
+
+TEST(HeapSnapshot) {
+ v8::HandleScope scope;
+
+ v8::Handle<v8::String> token1 = v8::String::New("token1");
+ v8::Handle<v8::Context> env1 = v8::Context::New();
+ env1->SetSecurityToken(token1);
+ env1->Enter();
+
+ CompileAndRunScript(
+ "function A1() {}\n"
+ "function B1(x) { this.x = x; }\n"
+ "function C1(x) { this.x1 = x; this.x2 = x; }\n"
+ "var a1 = new A1();\n"
+ "var b1_1 = new B1(a1), b1_2 = new B1(a1);\n"
+ "var c1 = new C1(a1);");
+
+ v8::Handle<v8::String> token2 = v8::String::New("token2");
+ v8::Handle<v8::Context> env2 = v8::Context::New();
+ env2->SetSecurityToken(token2);
+ env2->Enter();
+
+ CompileAndRunScript(
+ "function A2() {}\n"
+ "function B2(x) { return function() { return typeof x; }; }\n"
+ "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
+ "var a2 = new A2();\n"
+ "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
+ "var c2 = new C2(a2);");
+ const v8::HeapSnapshot* snapshot_env2 =
+ v8::HeapProfiler::TakeSnapshot(v8::String::New("env2"));
+ const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
+
+ // Verify, that JS global object of env2 doesn't have '..1'
+ // properties, but has '..2' properties.
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a1"));
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_1"));
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_2"));
+ CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c1"));
+ const v8::HeapGraphNode* a2_node =
+ GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a2");
+ CHECK_NE(NULL, a2_node);
+ CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_1"));
+ CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_2"));
+ CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c2"));
+
+ // Verify that anything related to '[ABC]1' is not reachable.
+ NamedEntriesDetector det;
+ i::HeapSnapshot* i_snapshot_env2 =
+ const_cast<i::HeapSnapshot*>(
+ reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2));
+ i_snapshot_env2->IterateEntries(&det);
+ CHECK(!det.has_A1);
+ CHECK(!det.has_B1);
+ CHECK(!det.has_C1);
+ CHECK(det.has_A2);
+ CHECK(det.has_B2);
+ CHECK(det.has_C2);
+
+ // Verify 'a2' object retainers. They are:
+ // - (global object).a2
+ // - c2.x1, c2.x2, c2[1]
+ // - b2_1 and b2_2 closures: via 'x' variable
+ CHECK_EQ(6, a2_node->GetRetainingPathsCount());
+ bool has_global_obj_a2_ref = false;
+ bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false;
+ bool has_b2_1_x_ref = false, has_b2_2_x_ref = false;
+ for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) {
+ const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i);
+ const int edges_count = path->GetEdgesCount();
+ CHECK_GT(edges_count, 0);
+ const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1);
+ v8::String::AsciiValue last_edge_name(last_edge->GetName());
+ if (strcmp("a2", *last_edge_name) == 0
+ && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY) {
+ has_global_obj_a2_ref = true;
+ continue;
+ }
+ CHECK_GT(edges_count, 1);
+ const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2);
+ v8::String::AsciiValue prev_edge_name(prev_edge->GetName());
+ if (strcmp("x1", *last_edge_name) == 0
+ && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY
+ && strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true;
+ if (strcmp("x2", *last_edge_name) == 0
+ && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY
+ && strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true;
+ if (strcmp("1", *last_edge_name) == 0
+ && last_edge->GetType() == v8::HeapGraphEdge::ELEMENT
+ && strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true;
+ if (strcmp("x", *last_edge_name) == 0
+ && last_edge->GetType() == v8::HeapGraphEdge::CONTEXT_VARIABLE
+ && strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true;
+ if (strcmp("x", *last_edge_name) == 0
+ && last_edge->GetType() == v8::HeapGraphEdge::CONTEXT_VARIABLE
+ && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true;
+ }
+ CHECK(has_global_obj_a2_ref);
+ CHECK(has_c2_x1_ref);
+ CHECK(has_c2_x2_ref);
+ CHECK(has_c2_1_ref);
+ CHECK(has_b2_1_x_ref);
+ CHECK(has_b2_2_x_ref);
+}
+
+
+TEST(HeapSnapshotCodeObjects) {
+ v8::HandleScope scope;
+ v8::Handle<v8::Context> env = v8::Context::New();
+ env->Enter();
+
+ CompileAndRunScript(
+ "function lazy(x) { return x - 1; }\n"
+ "function compiled(x) { return x + 1; }\n"
+ "compiled(1)");
+ const v8::HeapSnapshot* snapshot =
+ v8::HeapProfiler::TakeSnapshot(v8::String::New("code"));
+
+ const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+ const v8::HeapGraphNode* compiled =
+ GetProperty(global, v8::HeapGraphEdge::PROPERTY, "compiled");
+ CHECK_NE(NULL, compiled);
+ CHECK_EQ(v8::HeapGraphNode::CLOSURE, compiled->GetType());
+ const v8::HeapGraphNode* lazy =
+ GetProperty(global, v8::HeapGraphEdge::PROPERTY, "lazy");
+ CHECK_NE(NULL, lazy);
+ CHECK_EQ(v8::HeapGraphNode::CLOSURE, lazy->GetType());
+
+ // Find references to code.
+ const v8::HeapGraphNode* compiled_code =
+ GetProperty(compiled, v8::HeapGraphEdge::INTERNAL, "code");
+ CHECK_NE(NULL, compiled_code);
+ const v8::HeapGraphNode* lazy_code =
+ GetProperty(lazy, v8::HeapGraphEdge::INTERNAL, "code");
+ CHECK_NE(NULL, lazy_code);
+
+ // Verify that non-compiled code doesn't contain references to "x"
+ // literal, while compiled code does.
+ bool compiled_references_x = false, lazy_references_x = false;
+ for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) {
+ const v8::HeapGraphEdge* prop = compiled_code->GetChild(i);
+ const v8::HeapGraphNode* node = prop->GetToNode();
+ if (node->GetType() == v8::HeapGraphNode::CODE) {
+ if (HasString(node, "x")) {
+ compiled_references_x = true;
+ break;
+ }
+ }
+ }
+ for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) {
+ const v8::HeapGraphEdge* prop = lazy_code->GetChild(i);
+ const v8::HeapGraphNode* node = prop->GetToNode();
+ if (node->GetType() == v8::HeapGraphNode::CODE) {
+ if (HasString(node, "x")) {
+ lazy_references_x = true;
+ break;
+ }
+ }
+ }
+ CHECK(compiled_references_x);
+ CHECK(!lazy_references_x);
+}
+
#endif // ENABLE_LOGGING_AND_PROFILING
diff --git a/test/cctest/test-liveedit.cc b/test/cctest/test-liveedit.cc
index ec1a7a6..244980a 100644
--- a/test/cctest/test-liveedit.cc
+++ b/test/cctest/test-liveedit.cc
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef ENABLE_DEBUGGER_SUPPORT
+
#include <stdlib.h>
#include "v8.h"
@@ -172,3 +174,5 @@
CompareStrings("abbabababababaaabbabababababbabbbbbbbababa",
"bbbbabababbbabababbbabababababbabbababa");
}
+
+#endif // ENABLE_DEBUGGER_SUPPORT
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index c4c8a45..3ec25c9 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -98,9 +98,11 @@
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
static int register_code(int reg) {
return Debug::k_register_address << kDebugIdShift | reg;
}
+#endif // ENABLE_DEBUGGER_SUPPORT
TEST(ExternalReferenceEncoder) {
@@ -113,8 +115,10 @@
Encode(encoder, Runtime::kAbort));
CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
+#ifdef ENABLE_DEBUGGER_SUPPORT
CHECK_EQ(make_code(DEBUG_ADDRESS, register_code(3)),
Encode(encoder, Debug_Address(Debug::k_register_address, 3)));
+#endif // ENABLE_DEBUGGER_SUPPORT
ExternalReference keyed_load_function_prototype =
ExternalReference(&Counters::keyed_load_function_prototype);
CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
@@ -131,9 +135,11 @@
ExternalReference::address_of_real_stack_limit();
CHECK_EQ(make_code(UNCLASSIFIED, 5),
encoder.Encode(real_stack_limit_address.address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 12),
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ CHECK_EQ(make_code(UNCLASSIFIED, 15),
encoder.Encode(ExternalReference::debug_break().address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 7),
+#endif // ENABLE_DEBUGGER_SUPPORT
+ CHECK_EQ(make_code(UNCLASSIFIED, 10),
encoder.Encode(ExternalReference::new_space_start().address()));
CHECK_EQ(make_code(UNCLASSIFIED, 3),
encoder.Encode(ExternalReference::roots_address().address()));
@@ -150,8 +156,10 @@
decoder.Decode(make_code(RUNTIME_FUNCTION, Runtime::kAbort)));
CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
+#ifdef ENABLE_DEBUGGER_SUPPORT
CHECK_EQ(AddressOf(Debug_Address(Debug::k_register_address, 3)),
decoder.Decode(make_code(DEBUG_ADDRESS, register_code(3))));
+#endif // ENABLE_DEBUGGER_SUPPORT
ExternalReference keyed_load_function =
ExternalReference(&Counters::keyed_load_function_prototype);
CHECK_EQ(keyed_load_function.address(),
@@ -164,10 +172,12 @@
decoder.Decode(make_code(UNCLASSIFIED, 4)));
CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(),
decoder.Decode(make_code(UNCLASSIFIED, 5)));
+#ifdef ENABLE_DEBUGGER_SUPPORT
CHECK_EQ(ExternalReference::debug_break().address(),
- decoder.Decode(make_code(UNCLASSIFIED, 12)));
+ decoder.Decode(make_code(UNCLASSIFIED, 15)));
+#endif // ENABLE_DEBUGGER_SUPPORT
CHECK_EQ(ExternalReference::new_space_start().address(),
- decoder.Decode(make_code(UNCLASSIFIED, 7)));
+ decoder.Decode(make_code(UNCLASSIFIED, 10)));
}
diff --git a/test/mjsunit/apply.js b/test/mjsunit/apply.js
index a4b0fd7..cab7eb8 100644
--- a/test/mjsunit/apply.js
+++ b/test/mjsunit/apply.js
@@ -112,12 +112,25 @@
return arguments.length + arguments[arguments.length - 1];
}
+var stack_corner_case_failure = false;
+
for (var j = 1; j < 0x40000000; j <<= 1) {
try {
var a = new Array(j);
a[j - 1] = 42;
assertEquals(42 + j, al.apply(345, a));
} catch (e) {
+ if (e.toString().indexOf("Maximum call stack size exceeded") != -1) {
+ // For some combinations of build settings, it may be the case that the
+ // stack here is just tall enough to contain the array whose size is
+ // specified by j but is not tall enough to contain the activation
+ // record for the apply call. Allow one such corner case through,
+ // checking that the length check will do the right thing for an array
+ // the next size up.
+ assertEquals(false, stack_corner_case_failure);
+ stack_corner_case_failure = true;
+ continue;
+ }
assertTrue(e.toString().indexOf("Function.prototype.apply") != -1,
"exception does not contain Function.prototype.apply: " +
e.toString());
@@ -127,7 +140,7 @@
a = new Array(j);
a[j - 1] = 42;
al.apply(345, a);
- assertUnreachable("Apply of arrray with length " + a.length +
+ assertUnreachable("Apply of array with length " + a.length +
" should have thrown");
} catch (e) {
assertTrue(e.toString().indexOf("Function.prototype.apply") != -1,
diff --git a/test/mjsunit/debug-setbreakpoint.js b/test/mjsunit/debug-setbreakpoint.js
index 3981dc4..9661c95 100644
--- a/test/mjsunit/debug-setbreakpoint.js
+++ b/test/mjsunit/debug-setbreakpoint.js
@@ -116,7 +116,7 @@
mirror = debug.MakeMirror(o.a);
testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', true, false);
- testArguments(dcp, '{"type":"script","target":"sourceUrlScript","line":1}', true, true);
+ testArguments(dcp, '{"type":"script","target":"sourceUrlScript","line":0}', true, true);
// Indicate that all was processed.
listenerComplete = true;
@@ -134,6 +134,7 @@
};
function g() {
+ // Comment.
f();
};
@@ -184,3 +185,8 @@
sourceUrlFunc();
assertTrue(breakListenerCalled, "Break listener not called on breakpoint set by sourceURL");
+
+// Set a break point on a line with the comment, and check that actual position
+// is the next line after the comment.
+var number = Debug.setScriptBreakPointById(g_script_id, g_line + 1);
+assertEquals(g_line + 2, Debug.findBreakPoint(number).actual_location.line);
diff --git a/test/mjsunit/keyed-call-generic.js b/test/mjsunit/keyed-call-generic.js
index 0b49b3e..0314698 100644
--- a/test/mjsunit/keyed-call-generic.js
+++ b/test/mjsunit/keyed-call-generic.js
@@ -94,3 +94,20 @@
testMany(dict_array, first3num, first3num);
testMany(fast_prop, first3str, first3num);
testMany(normal_prop, first3str, first3num);
+
+
+function testException(receiver, keys, exceptions) {
+ for (var i = 0; i != 10; i++) {
+ for (var k = 0; k != keys.length; k++) {
+ var thrown = false;
+ try {
+ var result = receiver[keys[k]]();
+ } catch (e) {
+ thrown = true;
+ }
+ assertEquals(exceptions[k], thrown);
+ }
+ }
+}
+
+testException([zero, one, /* hole */ ], [0, 1, 2], [false, false, true]);
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 514d345..ceb5e62 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -34,9 +34,6 @@
# too long to run in debug mode on ARM.
fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm)
-# Issue 494: new snapshot code breaks mjsunit/apply on mac debug snapshot.
-apply: PASS, FAIL if ($system == macos && $mode == debug)
-
big-object-literal: PASS, SKIP if ($arch == arm)
# Issue 488: this test sometimes times out.
diff --git a/test/mjsunit/object-define-property.js b/test/mjsunit/object-define-property.js
index 46bfb34..b258aa7 100644
--- a/test/mjsunit/object-define-property.js
+++ b/test/mjsunit/object-define-property.js
@@ -714,3 +714,156 @@
} catch (e) {
assertTrue(/Cannot redefine property/.test(e));
}
+
+
+var obj6 = {};
+obj6[1] = 'foo';
+obj6[2] = 'bar';
+obj6[3] = '42';
+obj6[4] = '43';
+obj6[5] = '44';
+
+var descElement = { value: 'foobar' };
+var descElementNonConfigurable = { value: 'barfoo', configurable: false };
+var descElementNonWritable = { value: 'foofoo', writable: false };
+var descElementNonEnumerable = { value: 'barbar', enumerable: false };
+var descElementAllFalse = { value: 'foofalse',
+ configurable: false,
+ writable: false,
+ enumerable: false };
+
+
+// Redefine existing property.
+Object.defineProperty(obj6, '1', descElement);
+desc = Object.getOwnPropertyDescriptor(obj6, '1');
+assertEquals(desc.value, 'foobar');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(obj6, '2', descElementNonConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj6, '2');
+assertEquals(desc.value, 'barfoo');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Ensure that we can't overwrite the non configurable element.
+try {
+ Object.defineProperty(obj6, '2', descElement);
+ assertUnreachable();
+} catch (e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+Object.defineProperty(obj6, '3', descElementNonWritable);
+desc = Object.getOwnPropertyDescriptor(obj6, '3');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(obj6, '4', descElementNonEnumerable);
+desc = Object.getOwnPropertyDescriptor(obj6, '4');
+assertEquals(desc.value, 'barbar');
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(obj6, '5', descElementAllFalse);
+desc = Object.getOwnPropertyDescriptor(obj6, '5');
+assertEquals(desc.value, 'foofalse');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non existing property - all attributes should default to false.
+Object.defineProperty(obj6, '15', descElement);
+desc = Object.getOwnPropertyDescriptor(obj6, '15');
+assertEquals(desc.value, 'foobar');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Make sure that we can't redefine using direct access.
+obj6[15] ='overwrite';
+assertEquals(obj6[15],'foobar');
+
+
+// Repeat the above tests on an array.
+var arr = new Array();
+arr[1] = 'foo';
+arr[2] = 'bar';
+arr[3] = '42';
+arr[4] = '43';
+arr[5] = '44';
+
+var descElement = { value: 'foobar' };
+var descElementNonConfigurable = { value: 'barfoo', configurable: false };
+var descElementNonWritable = { value: 'foofoo', writable: false };
+var descElementNonEnumerable = { value: 'barbar', enumerable: false };
+var descElementAllFalse = { value: 'foofalse',
+ configurable: false,
+ writable: false,
+ enumerable: false };
+
+
+// Redefine existing property.
+Object.defineProperty(arr, '1', descElement);
+desc = Object.getOwnPropertyDescriptor(arr, '1');
+assertEquals(desc.value, 'foobar');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(arr, '2', descElementNonConfigurable);
+desc = Object.getOwnPropertyDescriptor(arr, '2');
+assertEquals(desc.value, 'barfoo');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Ensure that we can't overwrite the non configurable element.
+try {
+ Object.defineProperty(arr, '2', descElement);
+ assertUnreachable();
+} catch (e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+Object.defineProperty(arr, '3', descElementNonWritable);
+desc = Object.getOwnPropertyDescriptor(arr, '3');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(arr, '4', descElementNonEnumerable);
+desc = Object.getOwnPropertyDescriptor(arr, '4');
+assertEquals(desc.value, 'barbar');
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(arr, '5', descElementAllFalse);
+desc = Object.getOwnPropertyDescriptor(arr, '5');
+assertEquals(desc.value, 'foofalse');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non existing property - all attributes should default to false.
+Object.defineProperty(arr, '15', descElement);
+desc = Object.getOwnPropertyDescriptor(arr, '15');
+assertEquals(desc.value, 'foobar');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+
diff --git a/test/mjsunit/bugs/bug-619.js b/test/mjsunit/regress/regress-619.js
similarity index 92%
rename from test/mjsunit/bugs/bug-619.js
rename to test/mjsunit/regress/regress-619.js
index ef8ba80..24bdbc1 100644
--- a/test/mjsunit/bugs/bug-619.js
+++ b/test/mjsunit/regress/regress-619.js
@@ -25,9 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// When this bug is corrected move to object-define-property and add
-// additional tests for configurable in the same manner as existing tests
-// there.
+// Tests that Object.defineProperty works correctly on array indices.
+// Please see http://code.google.com/p/v8/issues/detail?id=619 for details.
var obj = {};
obj[1] = 42;
diff --git a/test/mjsunit/bugs/bug-619.js b/test/mjsunit/regress/regress-747.js
similarity index 68%
copy from test/mjsunit/bugs/bug-619.js
copy to test/mjsunit/regress/regress-747.js
index ef8ba80..6fcc000 100644
--- a/test/mjsunit/bugs/bug-619.js
+++ b/test/mjsunit/regress/regress-747.js
@@ -25,38 +25,32 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// When this bug is corrected move to object-define-property and add
-// additional tests for configurable in the same manner as existing tests
-// there.
+// Flags: --expose_gc
-var obj = {};
-obj[1] = 42;
-assertEquals(42, obj[1]);
-Object.defineProperty(obj, '1', {value:10, writable:false});
-assertEquals(10, obj[1]);
+// This test makes sure that we do flush code with heap allocated locals.
+// This can be a problem if eval is used within the scope.
+// See: http://code.google.com/p/v8/issues/detail?id=747
-// We should not be able to override obj[1].
-obj[1] = 5;
-assertEquals(10, obj[1]);
+(function() {
+ var x = 42;
+ this.callEval = function() {eval('x');};
+})();
-// Try on a range of numbers.
-for(var i = 0; i < 1024; i++) {
- obj[i] = 42;
-}
+try {
+ callEval();
+} catch (e) {
+ assertUnreachable();
+}
-for(var i = 0; i < 1024; i++) {
- Object.defineProperty(obj, i, {value: i, writable:false});
-}
+gc();
+gc();
+gc();
+gc();
+gc();
+gc();
-for(var i = 0; i < 1024; i++) {
- assertEquals(i, obj[i]);
-}
-
-for(var i = 0; i < 1024; i++) {
- obj[1] = 5;
-}
-
-for(var i = 0; i < 1024; i++) {
- assertEquals(i, obj[i]);
-}
-
+try {
+ callEval();
+} catch (e) {
+ assertUnreachable();
+}
diff --git a/test/mjsunit/samevalue.js b/test/mjsunit/samevalue.js
index 2de677e..6cb35e6 100644
--- a/test/mjsunit/samevalue.js
+++ b/test/mjsunit/samevalue.js
@@ -1,102 +1,102 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Flags: --expose-natives_as natives
-// Test the SameValue internal method.
-
-var obj1 = {x: 10, y: 11, z: "test"};
-var obj2 = {x: 10, y: 11, z: "test"};
-
-assertTrue(natives.SameValue(0, 0));
-assertTrue(natives.SameValue(+0, +0));
-assertTrue(natives.SameValue(-0, -0));
-assertTrue(natives.SameValue(1, 1));
-assertTrue(natives.SameValue(2, 2));
-assertTrue(natives.SameValue(-1, -1));
-assertTrue(natives.SameValue(0.5, 0.5));
-assertTrue(natives.SameValue(true, true));
-assertTrue(natives.SameValue(false, false));
-assertTrue(natives.SameValue(NaN, NaN));
-assertTrue(natives.SameValue(null, null));
-assertTrue(natives.SameValue("foo", "foo"));
-assertTrue(natives.SameValue(obj1, obj1));
-// Undefined values.
-assertTrue(natives.SameValue());
-assertTrue(natives.SameValue(undefined, undefined));
-
-assertFalse(natives.SameValue(0,1));
-assertFalse(natives.SameValue("foo", "bar"));
-assertFalse(natives.SameValue(obj1, obj2));
-assertFalse(natives.SameValue(true, false));
-
-assertFalse(natives.SameValue(obj1, true));
-assertFalse(natives.SameValue(obj1, "foo"));
-assertFalse(natives.SameValue(obj1, 1));
-assertFalse(natives.SameValue(obj1, undefined));
-assertFalse(natives.SameValue(obj1, NaN));
-
-assertFalse(natives.SameValue(undefined, true));
-assertFalse(natives.SameValue(undefined, "foo"));
-assertFalse(natives.SameValue(undefined, 1));
-assertFalse(natives.SameValue(undefined, obj1));
-assertFalse(natives.SameValue(undefined, NaN));
-
-assertFalse(natives.SameValue(NaN, true));
-assertFalse(natives.SameValue(NaN, "foo"));
-assertFalse(natives.SameValue(NaN, 1));
-assertFalse(natives.SameValue(NaN, obj1));
-assertFalse(natives.SameValue(NaN, undefined));
-
-assertFalse(natives.SameValue("foo", true));
-assertFalse(natives.SameValue("foo", 1));
-assertFalse(natives.SameValue("foo", obj1));
-assertFalse(natives.SameValue("foo", undefined));
-assertFalse(natives.SameValue("foo", NaN));
-
-assertFalse(natives.SameValue(true, 1));
-assertFalse(natives.SameValue(true, obj1));
-assertFalse(natives.SameValue(true, undefined));
-assertFalse(natives.SameValue(true, NaN));
-assertFalse(natives.SameValue(true, "foo"));
-
-assertFalse(natives.SameValue(1, true));
-assertFalse(natives.SameValue(1, obj1));
-assertFalse(natives.SameValue(1, undefined));
-assertFalse(natives.SameValue(1, NaN));
-assertFalse(natives.SameValue(1, "foo"));
-
-// Special string cases.
-assertFalse(natives.SameValue("1", 1));
-assertFalse(natives.SameValue("true", true));
-assertFalse(natives.SameValue("false", false));
-assertFalse(natives.SameValue("undefined", undefined));
-assertFalse(natives.SameValue("NaN", NaN));
-
-// -0 and +0 are should be different
-assertFalse(natives.SameValue(+0, -0));
-assertFalse(natives.SameValue(-0, +0));
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Flags: --expose-natives_as natives
+// Test the SameValue internal method.
+
+var obj1 = {x: 10, y: 11, z: "test"};
+var obj2 = {x: 10, y: 11, z: "test"};
+
+assertTrue(natives.SameValue(0, 0));
+assertTrue(natives.SameValue(+0, +0));
+assertTrue(natives.SameValue(-0, -0));
+assertTrue(natives.SameValue(1, 1));
+assertTrue(natives.SameValue(2, 2));
+assertTrue(natives.SameValue(-1, -1));
+assertTrue(natives.SameValue(0.5, 0.5));
+assertTrue(natives.SameValue(true, true));
+assertTrue(natives.SameValue(false, false));
+assertTrue(natives.SameValue(NaN, NaN));
+assertTrue(natives.SameValue(null, null));
+assertTrue(natives.SameValue("foo", "foo"));
+assertTrue(natives.SameValue(obj1, obj1));
+// Undefined values.
+assertTrue(natives.SameValue());
+assertTrue(natives.SameValue(undefined, undefined));
+
+assertFalse(natives.SameValue(0,1));
+assertFalse(natives.SameValue("foo", "bar"));
+assertFalse(natives.SameValue(obj1, obj2));
+assertFalse(natives.SameValue(true, false));
+
+assertFalse(natives.SameValue(obj1, true));
+assertFalse(natives.SameValue(obj1, "foo"));
+assertFalse(natives.SameValue(obj1, 1));
+assertFalse(natives.SameValue(obj1, undefined));
+assertFalse(natives.SameValue(obj1, NaN));
+
+assertFalse(natives.SameValue(undefined, true));
+assertFalse(natives.SameValue(undefined, "foo"));
+assertFalse(natives.SameValue(undefined, 1));
+assertFalse(natives.SameValue(undefined, obj1));
+assertFalse(natives.SameValue(undefined, NaN));
+
+assertFalse(natives.SameValue(NaN, true));
+assertFalse(natives.SameValue(NaN, "foo"));
+assertFalse(natives.SameValue(NaN, 1));
+assertFalse(natives.SameValue(NaN, obj1));
+assertFalse(natives.SameValue(NaN, undefined));
+
+assertFalse(natives.SameValue("foo", true));
+assertFalse(natives.SameValue("foo", 1));
+assertFalse(natives.SameValue("foo", obj1));
+assertFalse(natives.SameValue("foo", undefined));
+assertFalse(natives.SameValue("foo", NaN));
+
+assertFalse(natives.SameValue(true, 1));
+assertFalse(natives.SameValue(true, obj1));
+assertFalse(natives.SameValue(true, undefined));
+assertFalse(natives.SameValue(true, NaN));
+assertFalse(natives.SameValue(true, "foo"));
+
+assertFalse(natives.SameValue(1, true));
+assertFalse(natives.SameValue(1, obj1));
+assertFalse(natives.SameValue(1, undefined));
+assertFalse(natives.SameValue(1, NaN));
+assertFalse(natives.SameValue(1, "foo"));
+
+// Special string cases.
+assertFalse(natives.SameValue("1", 1));
+assertFalse(natives.SameValue("true", true));
+assertFalse(natives.SameValue("false", false));
+assertFalse(natives.SameValue("undefined", undefined));
+assertFalse(natives.SameValue("NaN", NaN));
+
+// -0 and +0 are should be different
+assertFalse(natives.SameValue(+0, -0));
+assertFalse(natives.SameValue(-0, +0));
diff --git a/test/mjsunit/string-externalize.js b/test/mjsunit/string-externalize.js
new file mode 100644
index 0000000..5b1f917
--- /dev/null
+++ b/test/mjsunit/string-externalize.js
@@ -0,0 +1,95 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-externalize-string
+
+var size = 1024;
+
+function test() {
+ var str = "";
+
+ // Build an ascii cons string.
+ for (var i = 0; i < size; i++) {
+ str += String.fromCharCode(i & 0x7f);
+ }
+ assertTrue(isAsciiString(str));
+
+ var twoByteExternalWithAsciiData =
+ "AA" + (function() { return "A"; })();
+ externalizeString(twoByteExternalWithAsciiData, true /* force two-byte */);
+ assertFalse(isAsciiString(twoByteExternalWithAsciiData));
+
+ var realTwoByteExternalString =
+ "\u1234\u1234" + (function() { return "\u1234"; })();
+ externalizeString(realTwoByteExternalString);
+ assertFalse(isAsciiString(realTwoByteExternalString));
+
+ assertTrue(isAsciiString(["a", twoByteExternalWithAsciiData].join("")));
+
+ // Appending a two-byte string that contains only ascii chars should
+ // still produce an ascii cons.
+ var str1 = str + twoByteExternalWithAsciiData;
+ assertTrue(isAsciiString(str1));
+
+ // Force flattening of the string.
+ var old_length = str1.length - twoByteExternalWithAsciiData.length;
+ for (var i = 0; i < old_length; i++) {
+ assertEquals(String.fromCharCode(i & 0x7f), str1[i]);
+ }
+ for (var i = old_length; i < str1.length; i++) {
+ assertEquals("A", str1[i]);
+ }
+
+ // Flattened string should still be ascii.
+ assertTrue(isAsciiString(str1));
+
+ // Lower-casing an ascii string should produce ascii.
+ assertTrue(isAsciiString(str1.toLowerCase()));
+
+ assertFalse(isAsciiString(["a", realTwoByteExternalString].join("")));
+
+ // Appending a real two-byte string should produce a two-byte cons.
+ var str2 = str + realTwoByteExternalString;
+ assertFalse(isAsciiString(str2));
+
+ // Force flattening of the string.
+ old_length = str2.length - realTwoByteExternalString.length;
+ for (var i = 0; i < old_length; i++) {
+ assertEquals(String.fromCharCode(i & 0x7f), str2[i]);
+ }
+ for (var i = old_length; i < str.length; i++) {
+ assertEquals("\u1234", str2[i]);
+ }
+
+ // Flattened string should still be two-byte.
+ assertFalse(isAsciiString(str2));
+}
+
+// Run the test many times to ensure IC-s don't break things.
+for (var i = 0; i < 10; i++) {
+ test();
+}