update V8 to TOT snapshot branch
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 0a392eb..db16bfc 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -394,6 +394,9 @@
v8::HandleScope scope;
LocalContext env;
Local<String> source = String::New(two_byte_source);
+ // Trigger GCs so that the newly allocated string moves to old gen.
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now
bool success = source->MakeExternal(new TestResource(two_byte_source));
CHECK(success);
Local<Script> script = Script::Compile(source);
@@ -416,6 +419,9 @@
v8::HandleScope scope;
LocalContext env;
Local<String> source = v8_str(c_source);
+ // Trigger GCs so that the newly allocated string moves to old gen.
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now
bool success = source->MakeExternal(
new TestAsciiResource(i::StrDup(c_source)));
CHECK(success);
@@ -432,6 +438,80 @@
}
+TEST(MakingExternalStringConditions) {
+ v8::HandleScope scope;
+ LocalContext env;
+
+ // Free some space in the new space so that we can check freshness.
+ i::Heap::CollectGarbage(0, i::NEW_SPACE);
+ i::Heap::CollectGarbage(0, i::NEW_SPACE);
+
+ Local<String> small_string = String::New(AsciiToTwoByteString("small"));
+ // We should refuse to externalize newly created small string.
+ CHECK(!small_string->CanMakeExternal());
+ // Trigger GCs so that the newly allocated string moves to old gen.
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now
+ // Old space strings should be accepted.
+ CHECK(small_string->CanMakeExternal());
+
+ small_string = String::New(AsciiToTwoByteString("small 2"));
+ // We should refuse externalizing newly created small string.
+ CHECK(!small_string->CanMakeExternal());
+ for (int i = 0; i < 100; i++) {
+ String::Value value(small_string);
+ }
+ // Frequently used strings should be accepted.
+ CHECK(small_string->CanMakeExternal());
+
+ const int buf_size = 10 * 1024;
+ char* buf = i::NewArray<char>(buf_size);
+ memset(buf, 'a', buf_size);
+ buf[buf_size - 1] = '\0';
+ Local<String> large_string = String::New(AsciiToTwoByteString(buf));
+ i::DeleteArray(buf);
+ // Large strings should be immediately accepted.
+ CHECK(large_string->CanMakeExternal());
+}
+
+
+TEST(MakingExternalAsciiStringConditions) {
+ v8::HandleScope scope;
+ LocalContext env;
+
+ // Free some space in the new space so that we can check freshness.
+ i::Heap::CollectGarbage(0, i::NEW_SPACE);
+ i::Heap::CollectGarbage(0, i::NEW_SPACE);
+
+ Local<String> small_string = String::New("small");
+ // We should refuse to externalize newly created small string.
+ CHECK(!small_string->CanMakeExternal());
+ // Trigger GCs so that the newly allocated string moves to old gen.
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now
+ i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now
+ // Old space strings should be accepted.
+ CHECK(small_string->CanMakeExternal());
+
+ small_string = String::New("small 2");
+ // We should refuse externalizing newly created small string.
+ CHECK(!small_string->CanMakeExternal());
+ for (int i = 0; i < 100; i++) {
+ String::Value value(small_string);
+ }
+ // Frequently used strings should be accepted.
+ CHECK(small_string->CanMakeExternal());
+
+ const int buf_size = 10 * 1024;
+ char* buf = i::NewArray<char>(buf_size);
+ memset(buf, 'a', buf_size);
+ buf[buf_size - 1] = '\0';
+ Local<String> large_string = String::New(buf);
+ i::DeleteArray(buf);
+ // Large strings should be immediately accepted.
+ CHECK(large_string->CanMakeExternal());
+}
+
+
THREADED_TEST(UsingExternalString) {
{
v8::HandleScope scope;
@@ -2448,6 +2528,33 @@
}
+static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property,
+ const AccessorInfo& info) {
+ // Set x on the prototype object and do not handle the get request.
+ v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
+ v8::Handle<v8::Object>::Cast(proto)->Set(v8_str("x"), v8::Integer::New(23));
+ return v8::Handle<Value>();
+}
+
+
+// This is a regression test for http://crbug.com/20104. Map
+// transitions should not interfere with post interceptor lookup.
+THREADED_TEST(NamedInterceptorMapTransitionRead) {
+ v8::HandleScope scope;
+ Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
+ Local<v8::ObjectTemplate> instance_template
+ = function_template->InstanceTemplate();
+ instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
+ LocalContext context;
+ context->Global()->Set(v8_str("F"), function_template->GetFunction());
+ // Create an instance of F and introduce a map transition for x.
+ CompileRun("var o = new F(); o.x = 23;");
+ // Create an instance of F and invoke the getter. The result should be 23.
+ Local<Value> result = CompileRun("o = new F(); o.x");
+ CHECK_EQ(result->Int32Value(), 23);
+}
+
+
static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
const AccessorInfo& info) {
ApiTestFuzzer::Fuzz();
@@ -2529,6 +2636,195 @@
}
+THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ obj->TurnOnAccessCheck();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var v = obj[0];"
+ " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
+THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
+ i::FLAG_allow_natives_syntax = true;
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var expected = i;"
+ " if (i == 5) {"
+ " %EnableAccessChecks(obj);"
+ " expected = undefined;"
+ " }"
+ " var v = obj[i];"
+ " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " if (i == 5) %DisableAccessChecks(obj);"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
+THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var v = obj[i];"
+ " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
+THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var expected = i;"
+ " if (i == 50) {"
+ " i = 'foobar';"
+ " expected = undefined;"
+ " }"
+ " var v = obj[i];"
+ " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
+THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "var original = obj;"
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var expected = i;"
+ " if (i == 50) {"
+ " obj = {50: 'foobar'};"
+ " expected = 'foobar';"
+ " }"
+ " var v = obj[i];"
+ " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " if (i == 50) obj = original;"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
+THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "var original = obj;"
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var expected = i;"
+ " if (i == 5) {"
+ " obj = 239;"
+ " expected = undefined;"
+ " }"
+ " var v = obj[i];"
+ " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " if (i == 5) obj = original;"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
+THREADED_TEST(IndexedInterceptorOnProto) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
+
+ LocalContext context;
+ Local<v8::Object> obj = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), obj);
+
+ const char* code =
+ "var o = {__proto__: obj};"
+ "try {"
+ " for (var i = 0; i < 100; i++) {"
+ " var v = o[i];"
+ " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
+ " }"
+ " 'PASSED'"
+ "} catch(e) {"
+ " e"
+ "}";
+ ExpectString(code, "PASSED");
+}
+
+
THREADED_TEST(MultiContexts) {
v8::HandleScope scope;
v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
@@ -4844,6 +5140,84 @@
}
+THREADED_TEST(SetPrototype) {
+ v8::HandleScope handle_scope;
+ LocalContext context;
+
+ Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
+ t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
+ Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
+ t1->SetHiddenPrototype(true);
+ t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
+ Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
+ t2->SetHiddenPrototype(true);
+ t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
+ Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
+ t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
+
+ Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
+ Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
+ Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
+ Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
+
+ // Setting the prototype on an object does not skip hidden prototypes.
+ CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+ CHECK(o0->SetPrototype(o1));
+ CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+ CHECK(o1->SetPrototype(o2));
+ CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+ CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
+ CHECK(o2->SetPrototype(o3));
+ CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
+ CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
+ CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
+
+ // Getting the prototype of o0 should get the first visible one
+ // which is o3. Therefore, z should not be defined on the prototype
+ // object.
+ Local<Value> proto = o0->Get(v8_str("__proto__"));
+ CHECK(proto->IsObject());
+ CHECK_EQ(v8::Handle<v8::Object>::Cast(proto), o3);
+
+ // However, Object::GetPrototype ignores hidden prototype.
+ Local<Value> proto0 = o0->GetPrototype();
+ CHECK(proto0->IsObject());
+ CHECK_EQ(v8::Handle<v8::Object>::Cast(proto0), o1);
+
+ Local<Value> proto1 = o1->GetPrototype();
+ CHECK(proto1->IsObject());
+ CHECK_EQ(v8::Handle<v8::Object>::Cast(proto1), o2);
+
+ Local<Value> proto2 = o2->GetPrototype();
+ CHECK(proto2->IsObject());
+ CHECK_EQ(v8::Handle<v8::Object>::Cast(proto2), o3);
+}
+
+
+THREADED_TEST(SetPrototypeThrows) {
+ v8::HandleScope handle_scope;
+ LocalContext context;
+
+ Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+
+ Local<v8::Object> o0 = t->GetFunction()->NewInstance();
+ Local<v8::Object> o1 = t->GetFunction()->NewInstance();
+
+ CHECK(o0->SetPrototype(o1));
+ // If setting the prototype leads to the cycle, SetPrototype should
+ // return false and keep VM in sane state.
+ v8::TryCatch try_catch;
+ CHECK(!o1->SetPrototype(o0));
+ CHECK(!try_catch.HasCaught());
+ ASSERT(!i::Top::has_pending_exception());
+
+ CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
+}
+
+
THREADED_TEST(GetterSetterExceptions) {
v8::HandleScope handle_scope;
LocalContext context;
@@ -5078,7 +5452,7 @@
static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
- //ApiTestFuzzer::Fuzz();
+ ApiTestFuzzer::Fuzz();
if (args.IsConstructCall()) {
if (args[0]->IsInt32()) {
return v8_num(-args[0]->Int32Value());
@@ -5891,6 +6265,294 @@
CHECK_EQ(239 * 10, value->Int32Value());
}
+static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
+ ++(*call_count);
+ if ((*call_count) % 20 == 0) {
+ v8::internal::Heap::CollectAllGarbage(true);
+ }
+ return v8::Handle<Value>();
+}
+
+static v8::Handle<Value> FastApiCallback_TrivialSignature(
+ const v8::Arguments& args) {
+ ApiTestFuzzer::Fuzz();
+ CHECK_EQ(args.This(), args.Holder());
+ CHECK(args.Data()->Equals(v8_str("method_data")));
+ return v8::Integer::New(args[0]->Int32Value() + 1);
+}
+
+static v8::Handle<Value> FastApiCallback_SimpleSignature(
+ const v8::Arguments& args) {
+ ApiTestFuzzer::Fuzz();
+ CHECK_EQ(args.This()->GetPrototype(), args.Holder());
+ CHECK(args.Data()->Equals(v8_str("method_data")));
+ // Note, we're using HasRealNamedProperty instead of Has to avoid
+ // invoking the interceptor again.
+ CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
+ return v8::Integer::New(args[0]->Int32Value() + 1);
+}
+
+// Helper to maximize the odds of object moving.
+static void GenerateSomeGarbage() {
+ CompileRun(
+ "var garbage;"
+ "for (var i = 0; i < 1000; i++) {"
+ " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
+ "}"
+ "garbage = undefined;");
+}
+
+THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
+ int interceptor_call_count = 0;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
+ v8_str("method_data"),
+ v8::Handle<v8::Signature>());
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
+ NULL, NULL, NULL, NULL,
+ v8::External::Wrap(&interceptor_call_count));
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "var result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = o.method(41);"
+ "}");
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+ CHECK_EQ(100, interceptor_call_count);
+}
+
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) {
+ int interceptor_call_count = 0;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
+ v8_str("method_data"),
+ v8::Signature::New(fun_templ));
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
+ NULL, NULL, NULL, NULL,
+ v8::External::Wrap(&interceptor_call_count));
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "o.foo = 17;"
+ "var receiver = {};"
+ "receiver.__proto__ = o;"
+ "var result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = receiver.method(41);"
+ "}");
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+ CHECK_EQ(100, interceptor_call_count);
+}
+
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
+ int interceptor_call_count = 0;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
+ v8_str("method_data"),
+ v8::Signature::New(fun_templ));
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
+ NULL, NULL, NULL, NULL,
+ v8::External::Wrap(&interceptor_call_count));
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "o.foo = 17;"
+ "var receiver = {};"
+ "receiver.__proto__ = o;"
+ "var result = 0;"
+ "var saved_result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = receiver.method(41);"
+ " if (i == 50) {"
+ " saved_result = result;"
+ " receiver = {method: function(x) { return x - 1 }};"
+ " }"
+ "}");
+ CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+ CHECK_GE(interceptor_call_count, 50);
+}
+
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
+ int interceptor_call_count = 0;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
+ v8_str("method_data"),
+ v8::Signature::New(fun_templ));
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
+ NULL, NULL, NULL, NULL,
+ v8::External::Wrap(&interceptor_call_count));
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "o.foo = 17;"
+ "var receiver = {};"
+ "receiver.__proto__ = o;"
+ "var result = 0;"
+ "var saved_result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = receiver.method(41);"
+ " if (i == 50) {"
+ " saved_result = result;"
+ " o.method = function(x) { return x - 1 };"
+ " }"
+ "}");
+ CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+ CHECK_GE(interceptor_call_count, 50);
+}
+
+THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
+ int interceptor_call_count = 0;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
+ v8_str("method_data"),
+ v8::Signature::New(fun_templ));
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
+ NULL, NULL, NULL, NULL,
+ v8::External::Wrap(&interceptor_call_count));
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::TryCatch try_catch;
+ v8::Handle<Value> value = CompileRun(
+ "o.foo = 17;"
+ "var receiver = {};"
+ "receiver.__proto__ = o;"
+ "var result = 0;"
+ "var saved_result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = receiver.method(41);"
+ " if (i == 50) {"
+ " saved_result = result;"
+ " receiver = {method: receiver.method};"
+ " }"
+ "}");
+ CHECK(try_catch.HasCaught());
+ CHECK_EQ(v8_str("TypeError: Illegal invocation"),
+ try_catch.Exception()->ToString());
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+ CHECK_GE(interceptor_call_count, 50);
+}
+
+THREADED_TEST(CallICFastApi_TrivialSignature) {
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
+ v8_str("method_data"),
+ v8::Handle<v8::Signature>());
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "var result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = o.method(41);"
+ "}");
+
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+THREADED_TEST(CallICFastApi_SimpleSignature) {
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
+ v8_str("method_data"),
+ v8::Signature::New(fun_templ));
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "o.foo = 17;"
+ "var receiver = {};"
+ "receiver.__proto__ = o;"
+ "var result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = receiver.method(41);"
+ "}");
+
+ CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+THREADED_TEST(CallICFastApi_SimpleSignature_Miss) {
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ v8::Handle<v8::FunctionTemplate> method_templ =
+ v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
+ v8_str("method_data"),
+ v8::Signature::New(fun_templ));
+ v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
+ proto_templ->Set(v8_str("method"), method_templ);
+ v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
+ LocalContext context;
+ v8::Handle<v8::Function> fun = fun_templ->GetFunction();
+ GenerateSomeGarbage();
+ context->Global()->Set(v8_str("o"), fun->NewInstance());
+ v8::Handle<Value> value = CompileRun(
+ "o.foo = 17;"
+ "var receiver = {};"
+ "receiver.__proto__ = o;"
+ "var result = 0;"
+ "var saved_result = 0;"
+ "for (var i = 0; i < 100; i++) {"
+ " result = receiver.method(41);"
+ " if (i == 50) {"
+ " saved_result = result;"
+ " receiver = {method: function(x) { return x - 1 }};"
+ " }"
+ "}");
+ CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
+ CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+}
+
static int interceptor_call_count = 0;
@@ -8927,3 +9589,138 @@
other_context.Dispose();
}
+
+
+THREADED_TEST(ScriptOrigin) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
+ v8::Handle<v8::String> script = v8::String::New(
+ "function f() {}\n\nfunction g() {}");
+ v8::Script::Compile(script, &origin)->Run();
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("f")));
+ v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("g")));
+
+ v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
+ CHECK_EQ("test", *v8::String::AsciiValue(script_origin_f.ResourceName()));
+ CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
+
+ v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
+ CHECK_EQ("test", *v8::String::AsciiValue(script_origin_g.ResourceName()));
+ CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
+}
+
+
+THREADED_TEST(ScriptLineNumber) {
+ v8::HandleScope scope;
+ LocalContext env;
+ v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
+ v8::Handle<v8::String> script = v8::String::New(
+ "function f() {}\n\nfunction g() {}");
+ v8::Script::Compile(script, &origin)->Run();
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("f")));
+ v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("g")));
+ CHECK_EQ(0, f->GetScriptLineNumber());
+ CHECK_EQ(2, g->GetScriptLineNumber());
+}
+
+
+static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
+ const AccessorInfo& info) {
+ return v8_num(42);
+}
+
+
+static void SetterWhichSetsYOnThisTo23(Local<String> name,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ info.This()->Set(v8_str("y"), v8_num(23));
+}
+
+
+THREADED_TEST(SetterOnConstructorPrototype) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetAccessor(v8_str("x"),
+ GetterWhichReturns42,
+ SetterWhichSetsYOnThisTo23);
+ LocalContext context;
+ context->Global()->Set(v8_str("P"), templ->NewInstance());
+ CompileRun("function C1() {"
+ " this.x = 23;"
+ "};"
+ "C1.prototype = P;"
+ "function C2() {"
+ " this.x = 23"
+ "};"
+ "C2.prototype = { };"
+ "C2.prototype.__proto__ = P;");
+
+ v8::Local<v8::Script> script;
+ script = v8::Script::Compile(v8_str("new C1();"));
+ for (int i = 0; i < 10; i++) {
+ v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
+ CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
+ }
+
+ script = v8::Script::Compile(v8_str("new C2();"));
+ for (int i = 0; i < 10; i++) {
+ v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
+ CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
+ }
+}
+
+
+static v8::Handle<Value> NamedPropertyGetterWhichReturns42(
+ Local<String> name, const AccessorInfo& info) {
+ return v8_num(42);
+}
+
+
+static v8::Handle<Value> NamedPropertySetterWhichSetsYOnThisTo23(
+ Local<String> name, Local<Value> value, const AccessorInfo& info) {
+ if (name->Equals(v8_str("x"))) {
+ info.This()->Set(v8_str("y"), v8_num(23));
+ }
+ return v8::Handle<Value>();
+}
+
+
+THREADED_TEST(InterceptorOnConstructorPrototype) {
+ v8::HandleScope scope;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
+ NamedPropertySetterWhichSetsYOnThisTo23);
+ LocalContext context;
+ context->Global()->Set(v8_str("P"), templ->NewInstance());
+ CompileRun("function C1() {"
+ " this.x = 23;"
+ "};"
+ "C1.prototype = P;"
+ "function C2() {"
+ " this.x = 23"
+ "};"
+ "C2.prototype = { };"
+ "C2.prototype.__proto__ = P;");
+
+ v8::Local<v8::Script> script;
+ script = v8::Script::Compile(v8_str("new C1();"));
+ for (int i = 0; i < 10; i++) {
+ v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
+ CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
+ }
+
+ script = v8::Script::Compile(v8_str("new C2();"));
+ for (int i = 0; i < 10; i++) {
+ v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
+ CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
+ CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
+ }
+}
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
new file mode 100644
index 0000000..ab011a7
--- /dev/null
+++ b/test/cctest/test-assembler-mips.cc
@@ -0,0 +1,257 @@
+// 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.
+
+#include "v8.h"
+
+#include "disassembler.h"
+#include "factory.h"
+#include "macro-assembler.h"
+#include "mips/macro-assembler-mips.h"
+#include "mips/simulator-mips.h"
+
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+// Define these function prototypes to match JSEntryFunction in execution.cc.
+typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
+typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
+typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
+
+
+static v8::Persistent<v8::Context> env;
+
+
+// The test framework does not accept flags on the command line, so we set them.
+static void InitializeVM() {
+ // Disable compilation of natives by specifying an empty natives file.
+ FLAG_natives_file = "";
+
+ // Enable generation of comments.
+ FLAG_debug_code = true;
+
+ if (env.IsEmpty()) {
+ env = v8::Context::New();
+ }
+}
+
+
+#define __ assm.
+
+TEST(MIPS0) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ MacroAssembler assm(NULL, 0);
+
+ // Addition.
+ __ addu(v0, a0, a1);
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+ int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
+ ::printf("f() = %d\n", res);
+ CHECK_EQ(0xabc, res);
+}
+
+
+TEST(MIPS1) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ MacroAssembler assm(NULL, 0);
+ Label L, C;
+
+ __ mov(a1, a0);
+ __ li(v0, 0);
+ __ b(&C);
+ __ nop();
+
+ __ bind(&L);
+ __ add(v0, v0, a1);
+ __ addiu(a1, a1, -1);
+
+ __ bind(&C);
+ __ xori(v1, a1, 0);
+ __ Branch(ne, &L, v1, Operand(0));
+ __ nop();
+
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
+ int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
+ ::printf("f() = %d\n", res);
+ CHECK_EQ(1275, res);
+}
+
+
+TEST(MIPS2) {
+ InitializeVM();
+ v8::HandleScope scope;
+
+ MacroAssembler assm(NULL, 0);
+
+ Label exit, error;
+
+ // ----- Test all instructions.
+
+ // Test lui, ori, and addiu, used in the li pseudo-instruction.
+ // This way we can then safely load registers with chosen values.
+
+ __ ori(t0, zero_reg, 0);
+ __ lui(t0, 0x1234);
+ __ ori(t0, t0, 0);
+ __ ori(t0, t0, 0x0f0f);
+ __ ori(t0, t0, 0xf0f0);
+ __ addiu(t1, t0, 1);
+ __ addiu(t2, t1, -0x10);
+
+ // Load values in temporary registers.
+ __ li(t0, 0x00000004);
+ __ li(t1, 0x00001234);
+ __ li(t2, 0x12345678);
+ __ li(t3, 0x7fffffff);
+ __ li(t4, 0xfffffffc);
+ __ li(t5, 0xffffedcc);
+ __ li(t6, 0xedcba988);
+ __ li(t7, 0x80000000);
+
+ // SPECIAL class.
+ __ srl(v0, t2, 8); // 0x00123456
+ __ sll(v0, v0, 11); // 0x91a2b000
+ __ sra(v0, v0, 3); // 0xf2345600
+ __ srav(v0, v0, t0); // 0xff234560
+ __ sllv(v0, v0, t0); // 0xf2345600
+ __ srlv(v0, v0, t0); // 0x0f234560
+ __ Branch(ne, &error, v0, Operand(0x0f234560));
+ __ nop();
+
+ __ add(v0, t0, t1); // 0x00001238
+ __ sub(v0, v0, t0); // 0x00001234
+ __ Branch(ne, &error, v0, Operand(0x00001234));
+ __ nop();
+ __ addu(v1, t3, t0);
+ __ Branch(ne, &error, v1, Operand(0x80000003));
+ __ nop();
+ __ subu(v1, t7, t0); // 0x7ffffffc
+ __ Branch(ne, &error, v1, Operand(0x7ffffffc));
+ __ nop();
+
+ __ and_(v0, t1, t2); // 0x00001230
+ __ or_(v0, v0, t1); // 0x00001234
+ __ xor_(v0, v0, t2); // 0x1234444c
+ __ nor(v0, v0, t2); // 0xedcba987
+ __ Branch(ne, &error, v0, Operand(0xedcba983));
+ __ nop();
+
+ __ slt(v0, t7, t3);
+ __ Branch(ne, &error, v0, Operand(0x1));
+ __ nop();
+ __ sltu(v0, t7, t3);
+ __ Branch(ne, &error, v0, Operand(0x0));
+ __ nop();
+ // End of SPECIAL class.
+
+ __ addi(v0, zero_reg, 0x7421); // 0x00007421
+ __ addi(v0, v0, -0x1); // 0x00007420
+ __ addiu(v0, v0, -0x20); // 0x00007400
+ __ Branch(ne, &error, v0, Operand(0x00007400));
+ __ nop();
+ __ addiu(v1, t3, 0x1); // 0x80000000
+ __ Branch(ne, &error, v1, Operand(0x80000000));
+ __ nop();
+
+ __ slti(v0, t1, 0x00002000); // 0x1
+ __ slti(v0, v0, 0xffff8000); // 0x0
+ __ Branch(ne, &error, v0, Operand(0x0));
+ __ nop();
+ __ sltiu(v0, t1, 0x00002000); // 0x1
+ __ sltiu(v0, v0, 0x00008000); // 0x1
+ __ Branch(ne, &error, v0, Operand(0x1));
+ __ nop();
+
+ __ andi(v0, t1, 0xf0f0); // 0x00001030
+ __ ori(v0, v0, 0x8a00); // 0x00009a30
+ __ xori(v0, v0, 0x83cc); // 0x000019fc
+ __ Branch(ne, &error, v0, Operand(0x000019fc));
+ __ nop();
+ __ lui(v1, 0x8123); // 0x81230000
+ __ Branch(ne, &error, v1, Operand(0x81230000));
+ __ nop();
+
+ // Everything was correctly executed. Load the expected result.
+ __ li(v0, 0x31415926);
+ __ b(&exit);
+ __ nop();
+
+ __ bind(&error);
+ // Got an error. Return a wrong result.
+
+ __ bind(&exit);
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Object* code = Heap::CreateCode(desc,
+ NULL,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Object>(Heap::undefined_value()));
+ CHECK(code->IsCode());
+#ifdef DEBUG
+ Code::cast(code)->Print();
+#endif
+ F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
+ int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
+ ::printf("f() = %d\n", res);
+ CHECK_EQ(0x31415926, res);
+}
+
+#undef __
diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index b5f12b9..471753c 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -120,6 +120,7 @@
0,
NULL,
NULL,
+ Handle<String>::null(),
NOT_NATIVES_CODE);
return Factory::NewFunctionFromBoilerplate(boilerplate,
Top::global_context());
@@ -322,3 +323,27 @@
CHECK_EQ(-1, GetScriptLineNumber(script, 100));
CHECK_EQ(-1, GetScriptLineNumber(script, -1));
}
+
+
+TEST(GetScriptLineNumber) {
+ LocalContext env;
+ v8::HandleScope scope;
+ v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
+ const char function_f[] = "function f() {}";
+ const int max_rows = 1000;
+ const int buffer_size = max_rows + sizeof(function_f);
+ ScopedVector<char> buffer(buffer_size);
+ memset(buffer.start(), '\n', buffer_size - 1);
+ buffer[buffer_size - 1] = '\0';
+
+ for (int i = 0; i < max_rows; ++i) {
+ if (i > 0)
+ buffer[i - 1] = '\n';
+ memcpy(&buffer[i], function_f, sizeof(function_f) - 1);
+ v8::Handle<v8::String> script_body = v8::String::New(buffer.start());
+ v8::Script::Compile(script_body, &origin)->Run();
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("f")));
+ CHECK_EQ(i, f->GetScriptLineNumber());
+ }
+}
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 92e18e0..b7c39b2 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -550,6 +550,15 @@
v8::Local<v8::Function> frame_script_data;
+// Source for The JavaScript function which picks out the script data from
+// AfterCompile event
+const char* compiled_script_data_source =
+ "function compiled_script_data(event_data) {"
+ " return event_data.script().data();"
+ "}";
+v8::Local<v8::Function> compiled_script_data;
+
+
// Source for The JavaScript function which returns the number of frames.
static const char* frame_count_source =
"function frame_count(exec_state) {"
@@ -647,6 +656,19 @@
script_data->WriteAscii(last_script_data_hit);
}
}
+ } else if (event == v8::AfterCompile && !compiled_script_data.IsEmpty()) {
+ const int argc = 1;
+ v8::Handle<v8::Value> argv[argc] = { event_data };
+ v8::Handle<v8::Value> result = compiled_script_data->Call(exec_state,
+ argc, argv);
+ if (result->IsUndefined()) {
+ last_script_data_hit[0] = '\0';
+ } else {
+ result = result->ToString();
+ CHECK(result->IsString());
+ v8::Handle<v8::String> script_data(result->ToString());
+ script_data->WriteAscii(last_script_data_hit);
+ }
}
}
@@ -3884,6 +3906,11 @@
}
+static int StringToInt(const char* s) {
+ return atoi(s); // NOLINT
+}
+
+
// We match parts of the message to get evaluate result int value.
int GetEvaluateIntResult(char *message) {
const char* value = "\"value\":";
@@ -3892,7 +3919,7 @@
return -1;
}
int res = -1;
- res = atoi(pos + strlen(value));
+ res = StringToInt(pos + strlen(value));
return res;
}
@@ -3905,7 +3932,7 @@
return -1;
}
int res = -1;
- res = atoi(pos + strlen(breakpoints));
+ res = StringToInt(pos + strlen(breakpoints));
return res;
}
@@ -3918,11 +3945,7 @@
return -1;
}
pos += strlen(prefix);
- char* pos_end = pos;
- int res = static_cast<int>(strtol(pos, &pos_end, 10));
- if (pos_end == pos) {
- return -1;
- }
+ int res = StringToInt(pos);
return res;
}
@@ -5231,6 +5254,9 @@
frame_script_data = CompileFunction(&env,
frame_script_data_source,
"frame_script_data");
+ compiled_script_data = CompileFunction(&env,
+ compiled_script_data_source,
+ "compiled_script_data");
v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
v8::Undefined());
@@ -5277,6 +5303,16 @@
CHECK_EQ(3, break_point_hit_count);
CHECK_EQ("new name", last_script_name_hit);
CHECK_EQ("abc 123", last_script_data_hit);
+
+ v8::Handle<v8::Script> script3 =
+ v8::Script::Compile(script, &origin2, NULL,
+ v8::String::New("in compile"));
+ CHECK_EQ("in compile", last_script_data_hit);
+ script3->Run();
+ f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+ f->Call(env->Global(), 0, NULL);
+ CHECK_EQ(4, break_point_hit_count);
+ CHECK_EQ("in compile", last_script_data_hit);
}
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index eca2c2b..9853af3 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -170,21 +170,110 @@
#endif // __linux__
-static int CheckThatProfilerWorks(int log_pos) {
- Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU);
+namespace {
+
+class ScopedLoggerInitializer {
+ public:
+ explicit ScopedLoggerInitializer(bool log, bool prof_lazy)
+ : saved_log_(i::FLAG_log),
+ saved_prof_lazy_(i::FLAG_prof_lazy),
+ saved_prof_(i::FLAG_prof),
+ saved_prof_auto_(i::FLAG_prof_auto),
+ trick_to_run_init_flags_(init_flags_(log, prof_lazy)),
+ need_to_set_up_logger_(i::V8::IsRunning()),
+ scope_(),
+ env_(v8::Context::New()) {
+ if (need_to_set_up_logger_) Logger::Setup();
+ env_->Enter();
+ }
+
+ ~ScopedLoggerInitializer() {
+ env_->Exit();
+ Logger::TearDown();
+ i::FLAG_prof_lazy = saved_prof_lazy_;
+ i::FLAG_prof = saved_prof_;
+ i::FLAG_prof_auto = saved_prof_auto_;
+ i::FLAG_log = saved_log_;
+ }
+
+ v8::Handle<v8::Context>& env() { return env_; }
+
+ private:
+ static bool init_flags_(bool log, bool prof_lazy) {
+ i::FLAG_log = log;
+ i::FLAG_prof = true;
+ i::FLAG_prof_lazy = prof_lazy;
+ i::FLAG_prof_auto = false;
+ i::FLAG_logfile = "*";
+ return prof_lazy;
+ }
+
+ const bool saved_log_;
+ const bool saved_prof_lazy_;
+ const bool saved_prof_;
+ const bool saved_prof_auto_;
+ const bool trick_to_run_init_flags_;
+ const bool need_to_set_up_logger_;
+ v8::HandleScope scope_;
+ v8::Handle<v8::Context> env_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer);
+};
+
+
+class LogBufferMatcher {
+ public:
+ LogBufferMatcher() {
+ // Skip all initially logged stuff.
+ log_pos_ = GetLogLines(0, &buffer_);
+ }
+
+ int log_pos() { return log_pos_; }
+
+ int GetNextChunk() {
+ int chunk_size = GetLogLines(log_pos_, &buffer_);
+ CHECK_GT(buffer_.length(), chunk_size);
+ buffer_[chunk_size] = '\0';
+ log_pos_ += chunk_size;
+ return chunk_size;
+ }
+
+ const char* Find(const char* substr) {
+ return strstr(buffer_.start(), substr);
+ }
+
+ const char* Find(const i::Vector<char>& substr) {
+ return Find(substr.start());
+ }
+
+ bool IsInSequence(const char* s1, const char* s2) {
+ const char* s1_pos = Find(s1);
+ const char* s2_pos = Find(s2);
+ CHECK_NE(NULL, s1_pos);
+ CHECK_NE(NULL, s2_pos);
+ return s1_pos < s2_pos;
+ }
+
+ void PrintBuffer() {
+ puts(buffer_.start());
+ }
+
+ private:
+ EmbeddedVector<char, 102400> buffer_;
+ int log_pos_;
+};
+
+} // namespace
+
+
+static void CheckThatProfilerWorks(LogBufferMatcher* matcher) {
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
CHECK(LoggerTestHelper::IsSamplerActive());
// Verify that the current map of compiled functions has been logged.
- EmbeddedVector<char, 102400> buffer;
- int map_log_size = GetLogLines(log_pos, &buffer);
- printf("map_log_size: %d\n", map_log_size);
- CHECK_GT(map_log_size, 0);
- CHECK_GT(buffer.length(), map_log_size);
- log_pos += map_log_size;
- // Check buffer contents.
- buffer[map_log_size] = '\0';
+ CHECK_GT(matcher->GetNextChunk(), 0);
const char* code_creation = "\ncode-creation,"; // eq. to /^code-creation,/
- CHECK_NE(NULL, strstr(buffer.start(), code_creation));
+ CHECK_NE(NULL, matcher->Find(code_creation));
#ifdef __linux__
// Intercept SIGPROF handler to make sure that the test process
@@ -204,7 +293,7 @@
i::OS::SNPrintF(script_src,
"function f%d(x) { return %d * x; }"
"for (var i = 0; i < 10000; ++i) { f%d(i); }",
- log_pos, log_pos, log_pos);
+ matcher->log_pos(), matcher->log_pos(), matcher->log_pos());
// Run code for 200 msecs to get some ticks.
const double end_time = i::OS::TimeCurrentMillis() + 200;
while (i::OS::TimeCurrentMillis() < end_time) {
@@ -213,7 +302,7 @@
i::OS::Sleep(1);
}
- Logger::PauseProfiler(v8::PROFILER_MODULE_CPU);
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 0);
CHECK(!LoggerTestHelper::IsSamplerActive());
// Wait 50 msecs to allow Profiler thread to process the last
@@ -221,68 +310,39 @@
i::OS::Sleep(50);
// Now we must have compiler and tick records.
- int log_size = GetLogLines(log_pos, &buffer);
- printf("log_size: %d\n", log_size);
- CHECK_GT(log_size, 0);
- CHECK_GT(buffer.length(), log_size);
- log_pos += log_size;
- // Check buffer contents.
- buffer[log_size] = '\0';
- printf("%s", buffer.start());
+ CHECK_GT(matcher->GetNextChunk(), 0);
+ matcher->PrintBuffer();
+ CHECK_NE(NULL, matcher->Find(code_creation));
const char* tick = "\ntick,";
- CHECK_NE(NULL, strstr(buffer.start(), code_creation));
- const bool ticks_found = strstr(buffer.start(), tick) != NULL;
+ const bool ticks_found = matcher->Find(tick) != NULL;
CHECK_EQ(was_sigprof_received, ticks_found);
-
- return log_pos;
}
TEST(ProfLazyMode) {
- const bool saved_prof_lazy = i::FLAG_prof_lazy;
- const bool saved_prof = i::FLAG_prof;
- const bool saved_prof_auto = i::FLAG_prof_auto;
- i::FLAG_prof = true;
- i::FLAG_prof_lazy = true;
- i::FLAG_prof_auto = false;
- i::FLAG_logfile = "*";
-
- // If tests are being run manually, V8 will be already initialized
- // by the bottom test.
- const bool need_to_set_up_logger = i::V8::IsRunning();
- v8::HandleScope scope;
- v8::Handle<v8::Context> env = v8::Context::New();
- if (need_to_set_up_logger) Logger::Setup();
- env->Enter();
+ ScopedLoggerInitializer initialize_logger(false, true);
// No sampling should happen prior to resuming profiler.
CHECK(!LoggerTestHelper::IsSamplerActive());
- EmbeddedVector<char, 102400> buffer;
+ LogBufferMatcher matcher;
// Nothing must be logged until profiling is resumed.
- int log_pos = GetLogLines(0, &buffer);
- CHECK_EQ(0, log_pos);
+ CHECK_EQ(0, matcher.log_pos());
CompileAndRunScript("var a = (function(x) { return x + 1; })(10);");
// Nothing must be logged while profiling is suspended.
- CHECK_EQ(0, GetLogLines(log_pos, &buffer));
+ CHECK_EQ(0, matcher.GetNextChunk());
- log_pos = CheckThatProfilerWorks(log_pos);
+ CheckThatProfilerWorks(&matcher);
CompileAndRunScript("var a = (function(x) { return x + 1; })(10);");
// No new data beyond last retrieved position.
- CHECK_EQ(0, GetLogLines(log_pos, &buffer));
+ CHECK_EQ(0, matcher.GetNextChunk());
// Check that profiling can be resumed again.
- CheckThatProfilerWorks(log_pos);
-
- env->Exit();
- Logger::TearDown();
- i::FLAG_prof_lazy = saved_prof_lazy;
- i::FLAG_prof = saved_prof;
- i::FLAG_prof_auto = saved_prof_auto;
+ CheckThatProfilerWorks(&matcher);
}
@@ -480,25 +540,8 @@
}
TEST(LogCallbacks) {
- const bool saved_prof_lazy = i::FLAG_prof_lazy;
- const bool saved_prof = i::FLAG_prof;
- const bool saved_prof_auto = i::FLAG_prof_auto;
- i::FLAG_prof = true;
- i::FLAG_prof_lazy = false;
- i::FLAG_prof_auto = false;
- i::FLAG_logfile = "*";
-
- // If tests are being run manually, V8 will be already initialized
- // by the bottom test.
- const bool need_to_set_up_logger = i::V8::IsRunning();
- v8::HandleScope scope;
- v8::Handle<v8::Context> env = v8::Context::New();
- if (need_to_set_up_logger) Logger::Setup();
- env->Enter();
-
- // Skip all initially logged stuff.
- EmbeddedVector<char, 102400> buffer;
- int log_pos = GetLogLines(0, &buffer);
+ ScopedLoggerInitializer initialize_logger(false, false);
+ LogBufferMatcher matcher;
v8::Persistent<v8::FunctionTemplate> obj =
v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
@@ -511,16 +554,14 @@
signature),
static_cast<v8::PropertyAttribute>(v8::DontDelete));
- env->Global()->Set(v8_str("Obj"), obj->GetFunction());
+ initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction());
CompileAndRunScript("Obj.prototype.method1.toString();");
i::Logger::LogCompiledFunctions();
- log_pos = GetLogLines(log_pos, &buffer);
- CHECK_GT(log_pos, 0);
- buffer[log_pos] = 0;
+ CHECK_GT(matcher.GetNextChunk(), 0);
const char* callback_rec = "code-creation,Callback,";
- char* pos = strstr(buffer.start(), callback_rec);
+ char* pos = const_cast<char*>(matcher.Find(callback_rec));
CHECK_NE(NULL, pos);
pos += strlen(callback_rec);
EmbeddedVector<char, 100> ref_data;
@@ -530,12 +571,6 @@
CHECK_EQ(ref_data.start(), pos);
obj.Dispose();
-
- env->Exit();
- Logger::TearDown();
- i::FLAG_prof_lazy = saved_prof_lazy;
- i::FLAG_prof = saved_prof;
- i::FLAG_prof_auto = saved_prof_auto;
}
@@ -555,25 +590,8 @@
}
TEST(LogAccessorCallbacks) {
- const bool saved_prof_lazy = i::FLAG_prof_lazy;
- const bool saved_prof = i::FLAG_prof;
- const bool saved_prof_auto = i::FLAG_prof_auto;
- i::FLAG_prof = true;
- i::FLAG_prof_lazy = false;
- i::FLAG_prof_auto = false;
- i::FLAG_logfile = "*";
-
- // If tests are being run manually, V8 will be already initialized
- // by the bottom test.
- const bool need_to_set_up_logger = i::V8::IsRunning();
- v8::HandleScope scope;
- v8::Handle<v8::Context> env = v8::Context::New();
- if (need_to_set_up_logger) Logger::Setup();
- env->Enter();
-
- // Skip all initially logged stuff.
- EmbeddedVector<char, 102400> buffer;
- int log_pos = GetLogLines(0, &buffer);
+ ScopedLoggerInitializer initialize_logger(false, false);
+ LogBufferMatcher matcher;
v8::Persistent<v8::FunctionTemplate> obj =
v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
@@ -583,34 +601,112 @@
inst->SetAccessor(v8::String::New("prop2"), Prop2Getter);
i::Logger::LogAccessorCallbacks();
- log_pos = GetLogLines(log_pos, &buffer);
- CHECK_GT(log_pos, 0);
- buffer[log_pos] = 0;
- printf("%s", buffer.start());
+ CHECK_GT(matcher.GetNextChunk(), 0);
+ matcher.PrintBuffer();
EmbeddedVector<char, 100> prop1_getter_record;
i::OS::SNPrintF(prop1_getter_record,
"code-creation,Callback,0x%" V8PRIxPTR ",1,\"get prop1\"",
Prop1Getter);
- CHECK_NE(NULL, strstr(buffer.start(), prop1_getter_record.start()));
+ CHECK_NE(NULL, matcher.Find(prop1_getter_record));
EmbeddedVector<char, 100> prop1_setter_record;
i::OS::SNPrintF(prop1_setter_record,
"code-creation,Callback,0x%" V8PRIxPTR ",1,\"set prop1\"",
Prop1Setter);
- CHECK_NE(NULL, strstr(buffer.start(), prop1_setter_record.start()));
+ CHECK_NE(NULL, matcher.Find(prop1_setter_record));
EmbeddedVector<char, 100> prop2_getter_record;
i::OS::SNPrintF(prop2_getter_record,
"code-creation,Callback,0x%" V8PRIxPTR ",1,\"get prop2\"",
Prop2Getter);
- CHECK_NE(NULL, strstr(buffer.start(), prop2_getter_record.start()));
+ CHECK_NE(NULL, matcher.Find(prop2_getter_record));
obj.Dispose();
+}
- env->Exit();
- Logger::TearDown();
- i::FLAG_prof_lazy = saved_prof_lazy;
- i::FLAG_prof = saved_prof;
- i::FLAG_prof_auto = saved_prof_auto;
+
+TEST(LogTags) {
+ ScopedLoggerInitializer initialize_logger(true, false);
+ LogBufferMatcher matcher;
+
+ const char* open_tag = "open-tag,";
+ const char* close_tag = "close-tag,";
+
+ // Check compatibility with the old style behavior.
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 0);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ CHECK_EQ(NULL, matcher.Find(open_tag));
+ CHECK_EQ(NULL, matcher.Find(close_tag));
+
+ const char* open_tag1 = "open-tag,1\n";
+ const char* close_tag1 = "close-tag,1\n";
+
+ // Check non-nested tag case.
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ CHECK_GT(matcher.GetNextChunk(), 0);
+ CHECK(matcher.IsInSequence(open_tag1, close_tag1));
+
+ const char* open_tag2 = "open-tag,2\n";
+ const char* close_tag2 = "close-tag,2\n";
+
+ // Check nested tags case.
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ CHECK_GT(matcher.GetNextChunk(), 0);
+ // open_tag1 < open_tag2 < close_tag2 < close_tag1
+ CHECK(matcher.IsInSequence(open_tag1, open_tag2));
+ CHECK(matcher.IsInSequence(open_tag2, close_tag2));
+ CHECK(matcher.IsInSequence(close_tag2, close_tag1));
+
+ // Check overlapped tags case.
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ CHECK_GT(matcher.GetNextChunk(), 0);
+ // open_tag1 < open_tag2 < close_tag1 < close_tag2
+ CHECK(matcher.IsInSequence(open_tag1, open_tag2));
+ CHECK(matcher.IsInSequence(open_tag2, close_tag1));
+ CHECK(matcher.IsInSequence(close_tag1, close_tag2));
+
+ const char* open_tag3 = "open-tag,3\n";
+ const char* close_tag3 = "close-tag,3\n";
+
+ // Check pausing overflow case.
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 2);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 2);
+ CHECK_EQ(v8::PROFILER_MODULE_CPU, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 1);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::PauseProfiler(v8::PROFILER_MODULE_CPU, 3);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 3);
+ CHECK_EQ(v8::PROFILER_MODULE_NONE, Logger::GetActiveProfilerModules());
+ // Must be no tags, because logging must be disabled.
+ CHECK_EQ(NULL, matcher.Find(open_tag3));
+ CHECK_EQ(NULL, matcher.Find(close_tag3));
}
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 18f6988..5335e9b 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -131,7 +131,7 @@
ExternalReference::address_of_real_stack_limit();
CHECK_EQ(make_code(UNCLASSIFIED, 5),
encoder.Encode(real_stack_limit_address.address()));
- CHECK_EQ(make_code(UNCLASSIFIED, 11),
+ CHECK_EQ(make_code(UNCLASSIFIED, 12),
encoder.Encode(ExternalReference::debug_break().address()));
CHECK_EQ(make_code(UNCLASSIFIED, 7),
encoder.Encode(ExternalReference::new_space_start().address()));
@@ -165,7 +165,7 @@
CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(),
decoder.Decode(make_code(UNCLASSIFIED, 5)));
CHECK_EQ(ExternalReference::debug_break().address(),
- decoder.Decode(make_code(UNCLASSIFIED, 11)));
+ decoder.Decode(make_code(UNCLASSIFIED, 12)));
CHECK_EQ(ExternalReference::new_space_start().address(),
decoder.Decode(make_code(UNCLASSIFIED, 7)));
}
diff --git a/test/cctest/test-utils.cc b/test/cctest/test-utils.cc
index 1d65e68..24b3c90 100644
--- a/test/cctest/test-utils.cc
+++ b/test/cctest/test-utils.cc
@@ -35,111 +35,6 @@
using namespace v8::internal;
-enum Mode {
- forward,
- backward_unsigned
-};
-
-
-static v8::internal::byte* Write(v8::internal::byte* p, Mode m, int x) {
- v8::internal::byte* q = NULL;
- switch (m) {
- case forward:
- q = EncodeInt(p, x);
- CHECK(q <= p + sizeof(x) + 1);
- break;
- case backward_unsigned:
- q = EncodeUnsignedIntBackward(p, x);
- CHECK(q >= p - sizeof(x) - 1);
- break;
- }
- return q;
-}
-
-
-static v8::internal::byte* Read(v8::internal::byte* p, Mode m, int x) {
- v8::internal::byte* q = NULL;
- int y;
- switch (m) {
- case forward:
- q = DecodeInt(p, &y);
- CHECK(q <= p + sizeof(y) + 1);
- break;
- case backward_unsigned: {
- unsigned int uy;
- q = DecodeUnsignedIntBackward(p, &uy);
- y = uy;
- CHECK(q >= p - sizeof(uy) - 1);
- break;
- }
- }
- CHECK(y == x);
- return q;
-}
-
-
-static v8::internal::byte* WriteMany(v8::internal::byte* p, Mode m, int x) {
- p = Write(p, m, x - 7);
- p = Write(p, m, x - 1);
- p = Write(p, m, x);
- p = Write(p, m, x + 1);
- p = Write(p, m, x + 2);
- p = Write(p, m, -x - 5);
- p = Write(p, m, -x - 1);
- p = Write(p, m, -x);
- p = Write(p, m, -x + 1);
- p = Write(p, m, -x + 3);
-
- return p;
-}
-
-
-static v8::internal::byte* ReadMany(v8::internal::byte* p, Mode m, int x) {
- p = Read(p, m, x - 7);
- p = Read(p, m, x - 1);
- p = Read(p, m, x);
- p = Read(p, m, x + 1);
- p = Read(p, m, x + 2);
- p = Read(p, m, -x - 5);
- p = Read(p, m, -x - 1);
- p = Read(p, m, -x);
- p = Read(p, m, -x + 1);
- p = Read(p, m, -x + 3);
-
- return p;
-}
-
-
-void ProcessValues(int* values, int n, Mode m) {
- v8::internal::byte buf[4 * KB]; // make this big enough
- v8::internal::byte* p0 = (m == forward ? buf : buf + ARRAY_SIZE(buf));
-
- v8::internal::byte* p = p0;
- for (int i = 0; i < n; i++) {
- p = WriteMany(p, m, values[i]);
- }
-
- v8::internal::byte* q = p0;
- for (int i = 0; i < n; i++) {
- q = ReadMany(q, m, values[i]);
- }
-
- CHECK(p == q);
-}
-
-
-TEST(Utils0) {
- int values[] = {
- 0, 1, 10, 16, 32, 64, 128, 256, 512, 1024, 1234, 5731,
- 10000, 100000, 1000000, 10000000, 100000000, 1000000000
- };
- const int n = ARRAY_SIZE(values);
-
- ProcessValues(values, n, forward);
- ProcessValues(values, n, backward_unsigned);
-}
-
-
TEST(Utils1) {
CHECK_EQ(-1000000, FastD2I(-1000000.0));
CHECK_EQ(-1, FastD2I(-1.0));
diff --git a/test/mjsunit/array-functions-prototype-misc.js b/test/mjsunit/array-functions-prototype-misc.js
new file mode 100644
index 0000000..0543c32
--- /dev/null
+++ b/test/mjsunit/array-functions-prototype-misc.js
@@ -0,0 +1,314 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/**
+ * @fileoverview Test splice, shift, unshift, slice and join on small
+ * and large arrays. Some of these methods are specified such that they
+ * should work on other objects too, so we test that too.
+ */
+
+var LARGE = 40000000;
+var VERYLARGE = 4000000000;
+
+// Nicer for firefox 1.5. Unless you uncomment the following two lines,
+// smjs will appear to hang on this file.
+//var LARGE = 40000;
+//var VERYLARGE = 40000;
+
+var fourhundredth = LARGE/400;
+
+function PseudoArray() {
+};
+
+for (var use_real_arrays = 0; use_real_arrays <= 1; use_real_arrays++) {
+ var poses = [0, 140, 20000, VERYLARGE];
+ var the_prototype;
+ var new_function;
+ var push_function;
+ var concat_function;
+ var slice_function;
+ var splice_function;
+ var splice_function_2;
+ var unshift_function;
+ var unshift_function_2;
+ var shift_function;
+ if (use_real_arrays) {
+ new_function = function(length) {
+ return new Array(length);
+ };
+ the_prototype = Array.prototype;
+ push_function = function(array, elt) {
+ return array.push(elt);
+ };
+ concat_function = function(array, other) {
+ return array.concat(other);
+ };
+ slice_function = function(array, start, len) {
+ return array.slice(start, len);
+ };
+ splice_function = function(array, start, len) {
+ return array.splice(start, len);
+ };
+ splice_function_2 = function(array, start, len, elt) {
+ return array.splice(start, len, elt);
+ };
+ unshift_function = function(array, elt) {
+ return array.unshift(elt);
+ };
+ unshift_function_2 = function(array, elt1, elt2) {
+ return array.unshift(elt1, elt2);
+ };
+ shift_function = function(array) {
+ return array.shift();
+ };
+ } else {
+ // Don't run largest size on non-arrays or we'll be here for ever.
+ poses.pop();
+ new_function = function(length) {
+ var obj = new PseudoArray();
+ obj.length = length;
+ return obj;
+ };
+ the_prototype = PseudoArray.prototype;
+ push_function = function(array, elt) {
+ array[array.length] = elt;
+ array.length++;
+ };
+ concat_function = function(array, other) {
+ return Array.prototype.concat.call(array, other);
+ };
+ slice_function = function(array, start, len) {
+ return Array.prototype.slice.call(array, start, len);
+ };
+ splice_function = function(array, start, len) {
+ return Array.prototype.splice.call(array, start, len);
+ };
+ splice_function_2 = function(array, start, len, elt) {
+ return Array.prototype.splice.call(array, start, len, elt);
+ };
+ unshift_function = function(array, elt) {
+ return Array.prototype.unshift.call(array, elt);
+ };
+ unshift_function_2 = function(array, elt1, elt2) {
+ return Array.prototype.unshift.call(array, elt1, elt2);
+ };
+ shift_function = function(array) {
+ return Array.prototype.shift.call(array);
+ };
+ }
+
+ for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
+ var pos = poses[pos_pos];
+ if (pos > 100) {
+ var a = new_function(pos);
+ assertEquals(pos, a.length);
+ push_function(a, 'foo');
+ assertEquals(pos + 1, a.length);
+ var b = ['bar'];
+ // Delete a huge number of holes.
+ var c = splice_function(a, 10, pos - 20);
+ assertEquals(pos - 20, c.length);
+ assertEquals(21, a.length);
+ }
+
+ // Add a numeric property to the prototype of the array class. This
+ // allows us to test some borderline stuff relative to the standard.
+ the_prototype["" + (pos + 1)] = 'baz';
+
+ if (use_real_arrays) {
+ // It seems quite clear from ECMAScript spec 15.4.4.5. Just call Get on
+ // every integer in the range.
+ // IE, Safari get this right.
+ // FF, Opera get this wrong.
+ var a = ['zero', ,'two'];
+ if (pos == 0) {
+ assertEquals("zero,baz,two", a.join(","));
+ }
+
+ // Concat only applies to real arrays, unlike most of the other methods.
+ var a = new_function(pos);
+ push_function(a, "con");
+ assertEquals("con", a[pos]);
+ assertEquals(pos + 1, a.length);
+ var b = new_function(0);
+ push_function(b, "cat");
+ assertEquals("cat", b[0]);
+ var ab = concat_function(a, b);
+ assertEquals("con", ab[pos]);
+ assertEquals(pos + 2, ab.length);
+ assertEquals("cat", ab[pos + 1]);
+ var ba = concat_function(b, a);
+ assertEquals("con", ba[pos + 1]);
+ assertEquals(pos + 2, ba.length);
+ assertEquals("cat", ba[0]);
+
+ // Join with '' as separator.
+ var join = a.join('');
+ assertEquals("con", join);
+ join = b.join('');
+ assertEquals("cat", join);
+ join = ab.join('');
+ assertEquals("concat", join);
+ join = ba.join('');
+ assertEquals("catcon", join);
+
+ var sparse = [];
+ sparse[pos + 1000] = 'is ';
+ sparse[pos + 271828] = 'time ';
+ sparse[pos + 31415] = 'the ';
+ sparse[pos + 012260199] = 'all ';
+ sparse[-1] = 'foo';
+ sparse[pos + 22591927] = 'good ';
+ sparse[pos + 1618033] = 'for ';
+ sparse[pos + 91] = ': Now ';
+ sparse[pos + 86720199] = 'men.';
+ sparse.hest = 'fisk';
+
+ assertEquals("baz: Now is the time for all good men.", sparse.join(''));
+ }
+
+ a = new_function(pos);
+ push_function(a, 'zero');
+ push_function(a, void 0);
+ push_function(a, 'two');
+
+ // Splice works differently from join.
+ // IE, Safari get this wrong.
+ // FF, Opera get this right.
+ // 15.4.4.12 line 24 says the object itself has to have the property...
+ var zero = splice_function(a, pos, 1);
+ assertEquals("undefined", typeof(a[pos]));
+ assertEquals("two", a[pos+1], "pos1:" + pos);
+ assertEquals(pos + 2, a.length, "a length");
+ assertEquals(1, zero.length, "zero length");
+ assertEquals("zero", zero[0]);
+
+ // 15.4.4.12 line 41 says the object itself has to have the property...
+ a = new_function(pos);
+ push_function(a, 'zero');
+ push_function(a, void 0);
+ push_function(a, 'two');
+ var nothing = splice_function_2(a, pos, 0, 'minus1');
+ assertEquals("minus1", a[pos]);
+ assertEquals("zero", a[pos+1]);
+ assertEquals("undefined", typeof(a[pos+2]), "toot!");
+ assertEquals("two", a[pos+3], "pos3");
+ assertEquals(pos + 4, a.length);
+ assertEquals(1, zero.length);
+ assertEquals("zero", zero[0]);
+
+ // 15.4.4.12 line 10 says the object itself has to have the property...
+ a = new_function(pos);
+ push_function(a, 'zero');
+ push_function(a, void 0);
+ push_function(a, 'two');
+ var one = splice_function(a, pos + 1, 1);
+ assertEquals("", one.join(","));
+ assertEquals(pos + 2, a.length);
+ assertEquals("zero", a[pos]);
+ assertEquals("two", a[pos+1]);
+
+ // Set things back to the way they were.
+ the_prototype[pos + 1] = undefined;
+
+ // Unshift.
+ var a = new_function(pos);
+ push_function(a, "foo");
+ assertEquals("foo", a[pos]);
+ assertEquals(pos + 1, a.length);
+ unshift_function(a, "bar");
+ assertEquals("foo", a[pos+1]);
+ assertEquals(pos + 2, a.length);
+ assertEquals("bar", a[0]);
+ unshift_function_2(a, "baz", "boo");
+ assertEquals("foo", a[pos+3]);
+ assertEquals(pos + 4, a.length);
+ assertEquals("baz", a[0]);
+ assertEquals("boo", a[1]);
+ assertEquals("bar", a[2]);
+
+ // Shift.
+ var baz = shift_function(a);
+ assertEquals("baz", baz);
+ assertEquals("boo", a[0]);
+ assertEquals(pos + 3, a.length);
+ assertEquals("foo", a[pos + 2]);
+
+ // Slice.
+ var bar = slice_function(a, 1, 0); // don't throw an exception please.
+ bar = slice_function(a, 1, 2);
+ assertEquals("bar", bar[0]);
+ assertEquals(1, bar.length);
+ assertEquals("bar", a[1]);
+
+ }
+}
+
+// Lets see if performance is reasonable.
+
+var a = new Array(LARGE + 10);
+for (var i = 0; i < a.length; i += 1000) {
+ a[i] = i;
+}
+
+// Take something near the end of the array.
+for (var i = 0; i < 100; i++) {
+ var top = a.splice(LARGE, 5);
+ assertEquals(5, top.length);
+ assertEquals(LARGE, top[0]);
+ assertEquals("undefined", typeof(top[1]));
+ assertEquals(LARGE + 5, a.length);
+ a.splice(LARGE, 0, LARGE);
+ a.length = LARGE + 10;
+}
+
+var a = new Array(LARGE + 10);
+for (var i = 0; i < a.length; i += fourhundredth) {
+ a[i] = i;
+}
+
+// Take something near the middle of the array.
+for (var i = 0; i < 10; i++) {
+ var top = a.splice(LARGE >> 1, 5);
+ assertEquals(5, top.length);
+ assertEquals(LARGE >> 1, top[0]);
+ assertEquals("undefined", typeof(top[1]));
+ assertEquals(LARGE + 5, a.length);
+ a.splice(LARGE >> 1, 0, LARGE >> 1, void 0, void 0, void 0, void 0);
+}
+
+
+// Test http://b/issue?id=1202711
+arr = [0];
+arr.length = 2;
+Array.prototype[1] = 1;
+assertEquals(1, arr.pop());
+assertEquals(0, arr.pop());
+Array.prototype[1] = undefined;
+
+// Test http://code.google.com/p/chromium/issues/detail?id=21860
+Array.prototype.push.apply([], [1].splice(0, -(-1 % 5)));
diff --git a/test/mjsunit/array-shift.js b/test/mjsunit/array-shift.js
new file mode 100644
index 0000000..d985b31
--- /dev/null
+++ b/test/mjsunit/array-shift.js
@@ -0,0 +1,71 @@
+// 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.
+
+// Check that shifting array of holes keeps it as array of holes
+(function() {
+ var array = new Array(10);
+ array.shift();
+ assertFalse(0 in array);
+})();
+
+// Now check the case with array of holes and some elements on prototype.
+(function() {
+ var len = 9;
+ var array = new Array(len);
+ Array.prototype[3] = "@3";
+ Array.prototype[7] = "@7";
+
+ assertEquals(len, array.length);
+ for (var i = 0; i < array.length; i++) {
+ assertEquals(array[i], Array.prototype[i]);
+ }
+
+ array.shift();
+
+ assertEquals(len - 1, array.length);
+ // Note that shift copies values from prototype into the array.
+ assertEquals(array[2], Array.prototype[3]);
+ assertTrue(array.hasOwnProperty(2));
+
+ assertEquals(array[6], Array.prototype[7]);
+ assertTrue(array.hasOwnProperty(6));
+
+ // ... but keeps the rest as holes:
+ Array.prototype[5] = "@5";
+ assertEquals(array[5], Array.prototype[5]);
+ assertFalse(array.hasOwnProperty(5));
+
+ assertEquals(array[3], Array.prototype[3]);
+ assertFalse(array.hasOwnProperty(3));
+
+ assertEquals(array[7], Array.prototype[7]);
+ assertFalse(array.hasOwnProperty(7));
+
+ assertTrue(delete Array.prototype[3]);
+ assertTrue(delete Array.prototype[5]);
+ assertTrue(delete Array.prototype[7]);
+})();
diff --git a/test/mjsunit/array-slice.js b/test/mjsunit/array-slice.js
new file mode 100644
index 0000000..c993a07
--- /dev/null
+++ b/test/mjsunit/array-slice.js
@@ -0,0 +1,162 @@
+// 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.
+
+// Check that slicing array of holes keeps it as array of holes
+(function() {
+ var array = new Array(10);
+ for (var i = 0; i < 7; i++) {
+ var sliced = array.slice();
+ assertEquals(array.length, sliced.length);
+ assertFalse(0 in sliced);
+ }
+})();
+
+
+// Check various forms of arguments omission.
+(function() {
+ var array = new Array(7);
+
+ for (var i = 0; i < 7; i++) {
+ assertEquals(array, array.slice());
+ assertEquals(array, array.slice(0));
+ assertEquals(array, array.slice(undefined));
+ assertEquals(array, array.slice("foobar"));
+ assertEquals(array, array.slice(undefined, undefined));
+ }
+})();
+
+
+// Check variants of negatives and positive indices.
+(function() {
+ var array = new Array(7);
+
+ for (var i = 0; i < 7; i++) {
+ assertEquals(7, array.slice(-100).length);
+ assertEquals(3, array.slice(-3).length);
+ assertEquals(3, array.slice(4).length);
+ assertEquals(1, array.slice(6).length);
+ assertEquals(0, array.slice(7).length);
+ assertEquals(0, array.slice(8).length);
+ assertEquals(0, array.slice(100).length);
+
+ assertEquals(0, array.slice(0, -100).length);
+ assertEquals(4, array.slice(0, -3).length);
+ assertEquals(4, array.slice(0, 4).length);
+ assertEquals(6, array.slice(0, 6).length);
+ assertEquals(7, array.slice(0, 7).length);
+ assertEquals(7, array.slice(0, 8).length);
+ assertEquals(7, array.slice(0, 100).length);
+
+ // Some exotic cases.
+
+ obj = { toString: function() { throw 'Exception'; } };
+
+ // More than 2 arguments:
+ assertEquals(7, array.slice(0, 7, obj, null, undefined).length);
+
+ // Custom conversion:
+ assertEquals(1, array.slice({valueOf: function() { return 1; }},
+ {toString: function() { return 2; }}).length);
+
+ // Throwing an exception in conversion:
+ try {
+ assertEquals(7, array.slice(0, obj).length);
+ throw 'Should have thrown';
+ } catch (e) {
+ assertEquals('Exception', e);
+ }
+ }
+})();
+
+
+// Nasty: modify the array in ToInteger.
+(function() {
+ var array = [];
+ var expected = []
+ bad_guy = { valueOf: function() { array.push(array.length); return -1; } };
+
+ for (var i = 0; i < 13; i++) {
+ var sliced = array.slice(bad_guy);
+ expected.push(i);
+ assertEquals(expected, array);
+ // According to the spec (15.4.4.10), length is calculated before
+ // performing ToInteger on arguments.
+ if (i == 0) {
+ assertEquals([], sliced); // Length was 0, nothing to get.
+ } else {
+ // Actually out of array [0..i] we get [i - 1] as length is i.
+ assertEquals([i - 1], sliced);
+ }
+ }
+})();
+
+
+// Now check the case with array of holes and some elements on prototype.
+(function() {
+ var len = 9;
+ var array = new Array(len);
+
+ var at3 = "@3";
+ var at7 = "@7";
+
+ for (var i = 0; i < 7; i++) {
+ Array.prototype[3] = at3;
+ Array.prototype[7] = at7;
+
+ assertEquals(len, array.length);
+ for (var i = 0; i < array.length; i++) {
+ assertEquals(array[i], Array.prototype[i]);
+ }
+
+ var sliced = array.slice();
+
+ assertEquals(len, sliced.length);
+
+ assertTrue(delete Array.prototype[3]);
+ assertTrue(delete Array.prototype[7]);
+
+ // Note that slice copies values from prototype into the array.
+ assertEquals(array[3], undefined);
+ assertFalse(array.hasOwnProperty(3));
+ assertEquals(sliced[3], at3);
+ assertTrue(sliced.hasOwnProperty(3));
+
+ assertEquals(array[7], undefined);
+ assertFalse(array.hasOwnProperty(7));
+ assertEquals(sliced[7], at7);
+ assertTrue(sliced.hasOwnProperty(7));
+
+ // ... but keeps the rest as holes:
+ Array.prototype[5] = "@5";
+ assertEquals(array[5], Array.prototype[5]);
+ assertFalse(array.hasOwnProperty(5));
+ assertEquals(sliced[5], Array.prototype[5]);
+ assertFalse(sliced.hasOwnProperty(5));
+
+ assertTrue(delete Array.prototype[5]);
+ }
+})();
diff --git a/test/mjsunit/array-splice.js b/test/mjsunit/array-splice.js
index 0543c32..18f81fe 100644
--- a/test/mjsunit/array-splice.js
+++ b/test/mjsunit/array-splice.js
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -25,290 +25,265 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-/**
- * @fileoverview Test splice, shift, unshift, slice and join on small
- * and large arrays. Some of these methods are specified such that they
- * should work on other objects too, so we test that too.
- */
+// Check that splicing array of holes keeps it as array of holes
+(function() {
+ for (var i = 0; i < 7; i++) {
+ var array = new Array(10);
+ var spliced = array.splice(1, 1, 'one', 'two');
+ assertEquals(1, spliced.length);
+ assertFalse(0 in spliced);
-var LARGE = 40000000;
-var VERYLARGE = 4000000000;
-
-// Nicer for firefox 1.5. Unless you uncomment the following two lines,
-// smjs will appear to hang on this file.
-//var LARGE = 40000;
-//var VERYLARGE = 40000;
-
-var fourhundredth = LARGE/400;
-
-function PseudoArray() {
-};
-
-for (var use_real_arrays = 0; use_real_arrays <= 1; use_real_arrays++) {
- var poses = [0, 140, 20000, VERYLARGE];
- var the_prototype;
- var new_function;
- var push_function;
- var concat_function;
- var slice_function;
- var splice_function;
- var splice_function_2;
- var unshift_function;
- var unshift_function_2;
- var shift_function;
- if (use_real_arrays) {
- new_function = function(length) {
- return new Array(length);
- };
- the_prototype = Array.prototype;
- push_function = function(array, elt) {
- return array.push(elt);
- };
- concat_function = function(array, other) {
- return array.concat(other);
- };
- slice_function = function(array, start, len) {
- return array.slice(start, len);
- };
- splice_function = function(array, start, len) {
- return array.splice(start, len);
- };
- splice_function_2 = function(array, start, len, elt) {
- return array.splice(start, len, elt);
- };
- unshift_function = function(array, elt) {
- return array.unshift(elt);
- };
- unshift_function_2 = function(array, elt1, elt2) {
- return array.unshift(elt1, elt2);
- };
- shift_function = function(array) {
- return array.shift();
- };
- } else {
- // Don't run largest size on non-arrays or we'll be here for ever.
- poses.pop();
- new_function = function(length) {
- var obj = new PseudoArray();
- obj.length = length;
- return obj;
- };
- the_prototype = PseudoArray.prototype;
- push_function = function(array, elt) {
- array[array.length] = elt;
- array.length++;
- };
- concat_function = function(array, other) {
- return Array.prototype.concat.call(array, other);
- };
- slice_function = function(array, start, len) {
- return Array.prototype.slice.call(array, start, len);
- };
- splice_function = function(array, start, len) {
- return Array.prototype.splice.call(array, start, len);
- };
- splice_function_2 = function(array, start, len, elt) {
- return Array.prototype.splice.call(array, start, len, elt);
- };
- unshift_function = function(array, elt) {
- return Array.prototype.unshift.call(array, elt);
- };
- unshift_function_2 = function(array, elt1, elt2) {
- return Array.prototype.unshift.call(array, elt1, elt2);
- };
- shift_function = function(array) {
- return Array.prototype.shift.call(array);
- };
+ assertEquals(11, array.length);
+ assertFalse(0 in array);
+ assertTrue(1 in array);
+ assertTrue(2 in array);
+ assertFalse(3 in array);
}
+})();
- for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
- var pos = poses[pos_pos];
- if (pos > 100) {
- var a = new_function(pos);
- assertEquals(pos, a.length);
- push_function(a, 'foo');
- assertEquals(pos + 1, a.length);
- var b = ['bar'];
- // Delete a huge number of holes.
- var c = splice_function(a, 10, pos - 20);
- assertEquals(pos - 20, c.length);
- assertEquals(21, a.length);
+
+// Check various forms of arguments omission.
+(function() {
+ var array;
+ for (var i = 0; i < 7; i++) {
+ // SpiderMonkey and JSC return undefined in the case where no
+ // arguments are given instead of using the implicit undefined
+ // arguments. This does not follow ECMA-262, but we do the same for
+ // compatibility.
+ // TraceMonkey follows ECMA-262 though.
+ array = [1, 2, 3]
+ assertEquals(undefined, array.splice());
+ assertEquals([1, 2, 3], array);
+
+ // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
+ // given differently from when an undefined delete count is given.
+ // This does not follow ECMA-262, but we do the same for
+ // compatibility.
+ array = [1, 2, 3]
+ assertEquals([1, 2, 3], array.splice(0));
+ assertEquals([], array);
+
+ array = [1, 2, 3]
+ assertEquals([1, 2, 3], array.splice(undefined));
+ assertEquals([], array);
+
+ array = [1, 2, 3]
+ assertEquals([1, 2, 3], array.splice("foobar"));
+ assertEquals([], array);
+
+ array = [1, 2, 3]
+ assertEquals([], array.splice(undefined, undefined));
+ assertEquals([1, 2, 3], array);
+
+ array = [1, 2, 3]
+ assertEquals([], array.splice("foobar", undefined));
+ assertEquals([1, 2, 3], array);
+
+ array = [1, 2, 3]
+ assertEquals([], array.splice(undefined, "foobar"));
+ assertEquals([1, 2, 3], array);
+
+ array = [1, 2, 3]
+ assertEquals([], array.splice("foobar", "foobar"));
+ assertEquals([1, 2, 3], array);
+ }
+})();
+
+
+// Check variants of negatives and positive indices.
+(function() {
+ var array, spliced;
+ for (var i = 0; i < 7; i++) {
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(-100);
+ assertEquals([], array);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(-3);
+ assertEquals([1, 2, 3, 4], array);
+ assertEquals([5, 6, 7], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(4);
+ assertEquals([1, 2, 3, 4], array);
+ assertEquals([5, 6, 7], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(6);
+ assertEquals([1, 2, 3, 4, 5, 6], array);
+ assertEquals([7], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(7);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], array);
+ assertEquals([], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(8);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], array);
+ assertEquals([], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(100);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], array);
+ assertEquals([], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, -100);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], array);
+ assertEquals([], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, -3);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], array);
+ assertEquals([], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, 4);
+ assertEquals([5, 6, 7], array);
+ assertEquals([1, 2, 3, 4], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, 6);
+ assertEquals([7], array);
+ assertEquals([1, 2, 3, 4, 5, 6], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, 7);
+ assertEquals([], array);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, 8);
+ assertEquals([], array);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
+
+ array = [1, 2, 3, 4, 5, 6, 7];
+ spliced = array.splice(0, 100);
+ assertEquals([], array);
+ assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
+
+ // Some exotic cases.
+ obj = { toString: function() { throw 'Exception'; } };
+
+ // Throwing an exception in conversion:
+ try {
+ [1, 2, 3].splice(obj, 3);
+ throw 'Should have thrown';
+ } catch (e) {
+ assertEquals('Exception', e);
}
- // Add a numeric property to the prototype of the array class. This
- // allows us to test some borderline stuff relative to the standard.
- the_prototype["" + (pos + 1)] = 'baz';
-
- if (use_real_arrays) {
- // It seems quite clear from ECMAScript spec 15.4.4.5. Just call Get on
- // every integer in the range.
- // IE, Safari get this right.
- // FF, Opera get this wrong.
- var a = ['zero', ,'two'];
- if (pos == 0) {
- assertEquals("zero,baz,two", a.join(","));
- }
-
- // Concat only applies to real arrays, unlike most of the other methods.
- var a = new_function(pos);
- push_function(a, "con");
- assertEquals("con", a[pos]);
- assertEquals(pos + 1, a.length);
- var b = new_function(0);
- push_function(b, "cat");
- assertEquals("cat", b[0]);
- var ab = concat_function(a, b);
- assertEquals("con", ab[pos]);
- assertEquals(pos + 2, ab.length);
- assertEquals("cat", ab[pos + 1]);
- var ba = concat_function(b, a);
- assertEquals("con", ba[pos + 1]);
- assertEquals(pos + 2, ba.length);
- assertEquals("cat", ba[0]);
-
- // Join with '' as separator.
- var join = a.join('');
- assertEquals("con", join);
- join = b.join('');
- assertEquals("cat", join);
- join = ab.join('');
- assertEquals("concat", join);
- join = ba.join('');
- assertEquals("catcon", join);
-
- var sparse = [];
- sparse[pos + 1000] = 'is ';
- sparse[pos + 271828] = 'time ';
- sparse[pos + 31415] = 'the ';
- sparse[pos + 012260199] = 'all ';
- sparse[-1] = 'foo';
- sparse[pos + 22591927] = 'good ';
- sparse[pos + 1618033] = 'for ';
- sparse[pos + 91] = ': Now ';
- sparse[pos + 86720199] = 'men.';
- sparse.hest = 'fisk';
-
- assertEquals("baz: Now is the time for all good men.", sparse.join(''));
+ try {
+ [1, 2, 3].splice(0, obj, 3);
+ throw 'Should have thrown';
+ } catch (e) {
+ assertEquals('Exception', e);
}
- a = new_function(pos);
- push_function(a, 'zero');
- push_function(a, void 0);
- push_function(a, 'two');
+ array = [1, 2, 3];
+ array.splice(0, 3, obj);
+ assertEquals(1, array.length);
- // Splice works differently from join.
- // IE, Safari get this wrong.
- // FF, Opera get this right.
- // 15.4.4.12 line 24 says the object itself has to have the property...
- var zero = splice_function(a, pos, 1);
- assertEquals("undefined", typeof(a[pos]));
- assertEquals("two", a[pos+1], "pos1:" + pos);
- assertEquals(pos + 2, a.length, "a length");
- assertEquals(1, zero.length, "zero length");
- assertEquals("zero", zero[0]);
-
- // 15.4.4.12 line 41 says the object itself has to have the property...
- a = new_function(pos);
- push_function(a, 'zero');
- push_function(a, void 0);
- push_function(a, 'two');
- var nothing = splice_function_2(a, pos, 0, 'minus1');
- assertEquals("minus1", a[pos]);
- assertEquals("zero", a[pos+1]);
- assertEquals("undefined", typeof(a[pos+2]), "toot!");
- assertEquals("two", a[pos+3], "pos3");
- assertEquals(pos + 4, a.length);
- assertEquals(1, zero.length);
- assertEquals("zero", zero[0]);
-
- // 15.4.4.12 line 10 says the object itself has to have the property...
- a = new_function(pos);
- push_function(a, 'zero');
- push_function(a, void 0);
- push_function(a, 'two');
- var one = splice_function(a, pos + 1, 1);
- assertEquals("", one.join(","));
- assertEquals(pos + 2, a.length);
- assertEquals("zero", a[pos]);
- assertEquals("two", a[pos+1]);
-
- // Set things back to the way they were.
- the_prototype[pos + 1] = undefined;
-
- // Unshift.
- var a = new_function(pos);
- push_function(a, "foo");
- assertEquals("foo", a[pos]);
- assertEquals(pos + 1, a.length);
- unshift_function(a, "bar");
- assertEquals("foo", a[pos+1]);
- assertEquals(pos + 2, a.length);
- assertEquals("bar", a[0]);
- unshift_function_2(a, "baz", "boo");
- assertEquals("foo", a[pos+3]);
- assertEquals(pos + 4, a.length);
- assertEquals("baz", a[0]);
- assertEquals("boo", a[1]);
- assertEquals("bar", a[2]);
-
- // Shift.
- var baz = shift_function(a);
- assertEquals("baz", baz);
- assertEquals("boo", a[0]);
- assertEquals(pos + 3, a.length);
- assertEquals("foo", a[pos + 2]);
-
- // Slice.
- var bar = slice_function(a, 1, 0); // don't throw an exception please.
- bar = slice_function(a, 1, 2);
- assertEquals("bar", bar[0]);
- assertEquals(1, bar.length);
- assertEquals("bar", a[1]);
-
+ // Custom conversion:
+ array = [1, 2, 3];
+ spliced = array.splice({valueOf: function() { return 1; }},
+ {toString: function() { return 2; }},
+ 'one', 'two');
+ assertEquals([2, 3], spliced);
+ assertEquals([1, 'one', 'two'], array);
}
-}
-
-// Lets see if performance is reasonable.
-
-var a = new Array(LARGE + 10);
-for (var i = 0; i < a.length; i += 1000) {
- a[i] = i;
-}
-
-// Take something near the end of the array.
-for (var i = 0; i < 100; i++) {
- var top = a.splice(LARGE, 5);
- assertEquals(5, top.length);
- assertEquals(LARGE, top[0]);
- assertEquals("undefined", typeof(top[1]));
- assertEquals(LARGE + 5, a.length);
- a.splice(LARGE, 0, LARGE);
- a.length = LARGE + 10;
-}
-
-var a = new Array(LARGE + 10);
-for (var i = 0; i < a.length; i += fourhundredth) {
- a[i] = i;
-}
-
-// Take something near the middle of the array.
-for (var i = 0; i < 10; i++) {
- var top = a.splice(LARGE >> 1, 5);
- assertEquals(5, top.length);
- assertEquals(LARGE >> 1, top[0]);
- assertEquals("undefined", typeof(top[1]));
- assertEquals(LARGE + 5, a.length);
- a.splice(LARGE >> 1, 0, LARGE >> 1, void 0, void 0, void 0, void 0);
-}
+})();
-// Test http://b/issue?id=1202711
-arr = [0];
-arr.length = 2;
-Array.prototype[1] = 1;
-assertEquals(1, arr.pop());
-assertEquals(0, arr.pop());
-Array.prototype[1] = undefined;
+// Nasty: modify the array in ToInteger.
+(function() {
+ var array = [];
+ var spliced;
-// Test http://code.google.com/p/chromium/issues/detail?id=21860
-Array.prototype.push.apply([], [1].splice(0, -(-1 % 5)));
+ for (var i = 0; i < 13; i++) {
+ bad_start = { valueOf: function() { array.push(2*i); return -1; } };
+ bad_count = { valueOf: function() { array.push(2*i + 1); return 1; } };
+ spliced = array.splice(bad_start, bad_count);
+ // According to the spec (15.4.4.12), length is calculated before
+ // performing ToInteger on arguments. However, v8 ignores elements
+ // we add while converting, so we need corrective pushes.
+ array.push(2*i); array.push(2*i + 1);
+ if (i == 0) {
+ assertEquals([], spliced); // Length was 0, nothing to get.
+ assertEquals([0, 1], array);
+ } else {
+ // When we start splice, array is [0 .. 2*i - 1], so we get
+ // as a result [2*i], this element is removed from the array,
+ // but [2 * i, 2 * i + 1] are added.
+ assertEquals([2 * i - 1], spliced);
+ assertEquals(2 * i, array[i]);
+ assertEquals(2 * i + 1, array[i + 1]);
+ }
+ }
+})();
+
+
+// Now check the case with array of holes and some elements on prototype.
+(function() {
+ var len = 9;
+
+ var at3 = "@3";
+ var at7 = "@7";
+
+ for (var i = 0; i < 7; i++) {
+ var array = new Array(len);
+ Array.prototype[3] = at3;
+ Array.prototype[7] = at7;
+
+ var spliced = array.splice(2, 2, 'one', undefined, 'two');
+
+ // Second hole (at index 3) of array turns into
+ // value of Array.prototype[3] while copying.
+ assertEquals([, at3], spliced);
+ assertEquals([, , 'one', undefined, 'two', , , at7, at7, ,], array);
+
+ // ... but array[7] is actually a hole:
+ assertTrue(delete Array.prototype[7]);
+ assertEquals(undefined, array[7]);
+
+ // and now check hasOwnProperty
+ assertFalse(array.hasOwnProperty(0));
+ assertFalse(array.hasOwnProperty(1));
+ assertTrue(array.hasOwnProperty(2));
+ assertTrue(array.hasOwnProperty(3));
+ assertTrue(array.hasOwnProperty(4));
+ assertFalse(array.hasOwnProperty(5));
+ assertFalse(array.hasOwnProperty(6));
+ assertFalse(array.hasOwnProperty(7));
+ assertTrue(array.hasOwnProperty(8));
+ assertFalse(array.hasOwnProperty(9));
+
+ // and now check couple of indices above length.
+ assertFalse(array.hasOwnProperty(10));
+ assertFalse(array.hasOwnProperty(15));
+ assertFalse(array.hasOwnProperty(31));
+ assertFalse(array.hasOwnProperty(63));
+ assertFalse(array.hasOwnProperty(2 << 32 - 1));
+ }
+})();
+
+
+// Check the behaviour when approaching maximal values for length.
+(function() {
+ for (var i = 0; i < 7; i++) {
+ try {
+ new Array((1 << 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
+ throw 'Should have thrown RangeError';
+ } catch (e) {
+ assertTrue(e instanceof RangeError);
+ }
+
+ // Check smi boundary
+ var bigNum = (1 << 30) - 3;
+ var array = new Array(bigNum);
+ array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
+ assertEquals(bigNum + 7, array.length);
+ }
+})();
diff --git a/test/mjsunit/array-unshift.js b/test/mjsunit/array-unshift.js
new file mode 100644
index 0000000..06a78a7
--- /dev/null
+++ b/test/mjsunit/array-unshift.js
@@ -0,0 +1,132 @@
+// 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.
+
+// Check that unshifting array of holes keeps the original array
+// as array of holes
+(function() {
+ var array = new Array(10);
+ assertEquals(13, array.unshift('1st', '2ns', '3rd'));
+ assertTrue(0 in array);
+ assertTrue(1 in array);
+ assertTrue(2 in array);
+ assertFalse(3 in array);
+})();
+
+
+// Check that unshif with no args has a side-effect of
+// feeling the holes with elements from the prototype
+// (if present, of course)
+(function() {
+ var len = 3;
+ var array = new Array(len);
+
+ var at0 = '@0';
+ var at2 = '@2';
+
+ Array.prototype[0] = at0;
+ Array.prototype[2] = at2;
+
+ // array owns nothing...
+ assertFalse(array.hasOwnProperty(0));
+ assertFalse(array.hasOwnProperty(1));
+ assertFalse(array.hasOwnProperty(2));
+
+ // ... but sees values from Array.prototype
+ assertEquals(array[0], at0);
+ assertEquals(array[1], undefined);
+ assertEquals(array[2], at2);
+
+ assertEquals(len, array.unshift());
+
+ assertTrue(delete Array.prototype[0]);
+ assertTrue(delete Array.prototype[2]);
+
+ // unshift makes array own 0 and 2...
+ assertTrue(array.hasOwnProperty(0));
+ assertFalse(array.hasOwnProperty(1));
+ assertTrue(array.hasOwnProperty(2));
+
+ // ... so they are not affected be delete.
+ assertEquals(array[0], at0);
+ assertEquals(array[1], undefined);
+ assertEquals(array[2], at2);
+})();
+
+
+// Now check the case with array of holes and some elements on prototype.
+(function() {
+ var len = 9;
+ var array = new Array(len);
+ Array.prototype[3] = "@3";
+ Array.prototype[7] = "@7";
+
+ assertEquals(len, array.length);
+ for (var i = 0; i < array.length; i++) {
+ assertEquals(array[i], Array.prototype[i]);
+ }
+
+ assertEquals(len + 1, array.unshift('head'));
+
+ assertEquals(len + 1, array.length);
+ // Note that unshift copies values from prototype into the array.
+ assertEquals(array[4], Array.prototype[3]);
+ assertTrue(array.hasOwnProperty(4));
+
+ assertEquals(array[8], Array.prototype[7]);
+ assertTrue(array.hasOwnProperty(8));
+
+ // ... but keeps the rest as holes:
+ Array.prototype[5] = "@5";
+ assertEquals(array[5], Array.prototype[5]);
+ assertFalse(array.hasOwnProperty(5));
+
+ assertEquals(array[3], Array.prototype[3]);
+ assertFalse(array.hasOwnProperty(3));
+
+ assertEquals(array[7], Array.prototype[7]);
+ assertFalse(array.hasOwnProperty(7));
+
+ assertTrue(delete Array.prototype[3]);
+ assertTrue(delete Array.prototype[5]);
+ assertTrue(delete Array.prototype[7]);
+})();
+
+// Check the behaviour when approaching maximal values for length.
+(function() {
+ for (var i = 0; i < 7; i++) {
+ try {
+ new Array((1 << 32) - 3).unshift(1, 2, 3, 4, 5);
+ throw 'Should have thrown RangeError';
+ } catch (e) {
+ assertTrue(e instanceof RangeError);
+ }
+
+ // Check smi boundary
+ var bigNum = (1 << 30) - 3;
+ assertEquals(bigNum + 7, new Array(bigNum).unshift(1, 2, 3, 4, 5, 6, 7));
+ }
+})();
diff --git a/test/mjsunit/bugs/618.js b/test/mjsunit/bugs/618.js
new file mode 100644
index 0000000..afa9929
--- /dev/null
+++ b/test/mjsunit/bugs/618.js
@@ -0,0 +1,86 @@
+// 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.
+
+// Simple class using inline constructor.
+function C1() {
+ this.x = 23;
+};
+var c1 = new C1();
+assertEquals(23, c1.x);
+assertEquals("undefined", typeof c1.y);
+
+// Add setter somewhere on the prototype chain after having constructed the
+// first instance.
+C1.prototype = { set x(value) { this.y = 23; } };
+var c1 = new C1();
+assertEquals("undefined", typeof c1.x);
+assertEquals(23, c1.y);
+
+// Simple class using inline constructor.
+function C2() {
+ this.x = 23;
+};
+var c2 = new C2();
+assertEquals(23, c2.x);
+assertEquals("undefined", typeof c2.y);
+
+// Add setter somewhere on the prototype chain after having constructed the
+// first instance.
+C2.prototype.__proto__ = { set x(value) { this.y = 23; } };
+var c2 = new C2();
+assertEquals("undefined", typeof c2.x);
+assertEquals(23, c2.y);
+
+// Simple class using inline constructor.
+function C3() {
+ this.x = 23;
+};
+var c3 = new C3();
+assertEquals(23, c3.x);
+assertEquals("undefined", typeof c3.y);
+
+// Add setter somewhere on the prototype chain after having constructed the
+// first instance.
+C3.prototype.__defineSetter__('x', function(value) { this.y = 23; });
+var c3 = new C3();
+assertEquals("undefined", typeof c3.x);
+assertEquals(23, c3.y);
+
+// Simple class using inline constructor.
+function C4() {
+ this.x = 23;
+};
+var c4 = new C4();
+assertEquals(23, c4.x);
+assertEquals("undefined", typeof c4.y);
+
+// Add setter somewhere on the prototype chain after having constructed the
+// first instance.
+C4.prototype.__proto__.__defineSetter__('x', function(value) { this.y = 23; });
+var c4 = new C4();
+assertEquals("undefined", typeof c4.x);
+assertEquals(23, c4.y);
diff --git a/test/mjsunit/bugs/bug-619.js b/test/mjsunit/bugs/bug-619.js
new file mode 100644
index 0000000..ef8ba80
--- /dev/null
+++ b/test/mjsunit/bugs/bug-619.js
@@ -0,0 +1,62 @@
+// 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.
+
+// When this bug is corrected move to object-define-property and add
+// additional tests for configurable in the same manner as existing tests
+// there.
+
+var obj = {};
+obj[1] = 42;
+assertEquals(42, obj[1]);
+Object.defineProperty(obj, '1', {value:10, writable:false});
+assertEquals(10, obj[1]);
+
+// We should not be able to override obj[1].
+obj[1] = 5;
+assertEquals(10, obj[1]);
+
+// Try on a range of numbers.
+for(var i = 0; i < 1024; i++) {
+ obj[i] = 42;
+}
+
+for(var i = 0; i < 1024; i++) {
+ Object.defineProperty(obj, i, {value: i, writable:false});
+}
+
+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]);
+}
+
diff --git a/test/mjsunit/codegen-coverage.js b/test/mjsunit/codegen-coverage.js
index d5e7769..42c371b 100644
--- a/test/mjsunit/codegen-coverage.js
+++ b/test/mjsunit/codegen-coverage.js
@@ -25,64 +25,110 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Test the paths in the code generator where values in specific
-// registers get moved around so that the shift operation can use
-// register ECX on ia32 for the shift amount. Other codegen coverage
-// tests should go here too.
+// Flags: --nofull-compiler --nofast-compiler
-
-
+// Test paths in the code generator where values in specific registers
+// get moved around.
function identity(x) {
return x;
}
function cover_codegen_paths() {
var x = 1;
- var a; // Register EAX
- var b; // Register EBX
- var c; // Register ECX
- var d; // Register EDX
- // Register ESI is already used.
- var di; // Register EDI
+
+ // This test depends on the fixed order of register allocation. We try to
+ // get values in specific registers (ia32, x64):
+ var a; // Register eax, rax.
+ var b; // Register ebx, rbx.
+ var c; // Register ecx, rcx.
+ var d; // Register edx, rdx.
+ var di; // Register edi, rdi.
while (x == 1) {
+ // The call will spill registers and leave x in {eax,rax}.
x = identity(1);
+ // The add will spill x and reuse {eax,rax} for the result.
a = x + 1;
+ // A fresh register {ebx,rbx} will be allocated for x, then reused for
+ // the result.
+ b = x + 1;
+ // Et cetera.
c = x + 1;
d = x + 1;
- b = x + 1;
di = x + 1;
// Locals are in the corresponding registers here.
- assertEquals(c << a, 8);
+ assertEquals(8, c << a);
x = identity(1);
a = x + 1;
+ b = x + 1;
c = x + 1;
d = x + 1;
- b = x + 1;
di = x + 1;
- // Locals are in the corresponding registers here.
- assertEquals(a << c, 8);
+ assertEquals(8, a << c);
x = identity(1);
a = x + 1;
+ b = x + 1;
c = x + 1;
d = x + 1;
- b = x + 1;
di = x + 1;
- // Locals are in the corresponding registers here.
c = 0; // Free register ecx.
- assertEquals(a << d, 8);
+ assertEquals(8, a << d);
x = identity(1);
a = x + 1;
+ b = x + 1;
c = x + 1;
d = x + 1;
- b = x + 1;
di = x + 1;
- // Locals are in the corresponding registers here.
b = 0; // Free register ebx.
- assertEquals(a << d, 8);
+ assertEquals(8, a << d);
+
+ // Test the non-commutative subtraction operation with a smi on the
+ // left, all available registers on the right, and a non-smi result.
+ x = identity(-1073741824); // Least (31-bit) smi.
+ a = x + 1; // Still a smi, the greatest smi negated.
+ b = x + 1;
+ c = x + 1;
+ d = x + 1;
+ di = x + 1;
+ // Subtraction should overflow the 31-bit smi range. The result
+ // (1073741824) is outside the 31-bit smi range so it doesn't hit the
+ // "unsafe smi" code that spills a register.
+ assertEquals(1073741824, 1 - a);
+
+ x = identity(-1073741824);
+ a = x + 1;
+ b = x + 1;
+ c = x + 1;
+ d = x + 1;
+ di = x + 1;
+ assertEquals(1073741824, 1 - b);
+
+ x = identity(-1073741824);
+ a = x + 1;
+ b = x + 1;
+ c = x + 1;
+ d = x + 1;
+ di = x + 1;
+ assertEquals(1073741824, 1 - c);
+
+ x = identity(-1073741824);
+ a = x + 1;
+ b = x + 1;
+ c = x + 1;
+ d = x + 1;
+ di = x + 1;
+ assertEquals(1073741824, 1 - d);
+
+ x = identity(-1073741824);
+ a = x + 1;
+ b = x + 1;
+ c = x + 1;
+ d = x + 1;
+ di = x + 1;
+ assertEquals(1073741824, 1 - di);
x = 3;
}
diff --git a/test/mjsunit/compiler/assignment.js b/test/mjsunit/compiler/assignment.js
new file mode 100644
index 0000000..ee2d323
--- /dev/null
+++ b/test/mjsunit/compiler/assignment.js
@@ -0,0 +1,264 @@
+// 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.
+
+// Tests for compound assignments at the top level
+
+z = 2;
+z += 4;
+
+assertEquals(z, 6);
+
+a = new Array(10);
+
+a[2] += 7;
+a[2] = 15;
+a[2] += 2;
+
+assertEquals(17, a[2]);
+
+b = new Object();
+b.foo = 5;
+b.foo += 12;
+
+assertEquals(17, b.foo);
+
+// Test compound assignments in an anonymous function with local variables.
+(function () {
+ var z = 2;
+ z += 4;
+
+ assertEquals(z, 6);
+
+ var a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ var b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+})();
+
+// Test compound assignments in an anonymous function with global variables.
+(function () {
+ z = 2;
+ z += 4;
+
+ assertEquals(z, 6);
+
+ a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+})();
+
+// Test compound assignments in a named function with local variables.
+function foo() {
+ var z = 3;
+ z += 4;
+
+ assertEquals(z, 7);
+
+ var a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ var b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+}
+
+foo();
+
+// Test compound assignments in a named function with global variables.
+function bar() {
+ z = 2;
+ z += 5;
+
+ assertEquals(z, 7);
+
+ a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+}
+
+bar();
+
+// Entire series of tests repeated, in loops.
+// -------------------------------------------
+// Tests for compound assignments in a loop at the top level
+
+for (i = 0; i < 5; ++i) {
+ z = 2;
+ z += 4;
+
+ assertEquals(z, 6);
+
+ a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+}
+
+// Test compound assignments in an anonymous function with local variables.
+(function () {
+ for (var i = 0; i < 5; ++i) {
+ var z = 2;
+ z += 4;
+
+ assertEquals(z, 6);
+
+ var a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ var b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+ }
+})();
+
+// Test compound assignments in an anonymous function with global variables.
+(function () {
+ for (i = 0; i < 5; ++i) {
+ z = 2;
+ z += 4;
+
+ assertEquals(z, 6);
+
+ a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+ }
+})();
+
+// Test compound assignments in a named function with local variables.
+function foo_loop() {
+ for (i = 0; i < 5; ++i) {
+ var z = 3;
+ z += 4;
+
+ assertEquals(z, 7);
+
+ var a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ var b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+ }
+}
+
+foo_loop();
+
+// Test compound assignments in a named function with global variables.
+function bar_loop() {
+ for (i = 0; i < 5; ++i) {
+ z = 2;
+ z += 5;
+
+ assertEquals(z, 7);
+
+ a = new Array(10);
+
+ a[2] += 7;
+ a[2] = 15;
+ a[2] += 2;
+
+ assertEquals(17, a[2]);
+
+ b = new Object();
+ b.foo = 5;
+ b.foo += 12;
+
+ assertEquals(17, b.foo);
+ }
+}
+
+bar_loop();
diff --git a/test/mjsunit/compiler/simple-bailouts.js b/test/mjsunit/compiler/simple-bailouts.js
new file mode 100644
index 0000000..af80b7f
--- /dev/null
+++ b/test/mjsunit/compiler/simple-bailouts.js
@@ -0,0 +1,127 @@
+// 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: --fast-compiler
+
+function Test() {
+ this.result = 0;
+ this.x = 0;
+ this.y = 0;
+ this.z = 0;
+}
+var a = 1;
+var b = 2;
+var c = 4;
+var d = 8;
+
+// Test operations expected to stay on the fast path. Enumerate all binary
+// trees with <= 4 leaves.
+Test.prototype.test0 = function () {
+ this.result = a | b;
+};
+
+Test.prototype.test1 = function() {
+ this.result = (a | b) | c;
+};
+
+Test.prototype.test2 = function() {
+ this.result = a | (b | c);
+};
+
+Test.prototype.test3 = function() {
+ this.result = ((a | b) | c) | d;
+};
+
+Test.prototype.test4 = function() {
+ this.result = (a | (b | c)) | d;
+};
+
+Test.prototype.test5 = function() {
+ this.result = (a | b) | (c | d);
+};
+
+Test.prototype.test6 = function() {
+ this.result = a | ((b | c) | d);
+};
+
+Test.prototype.test7 = function() {
+ this.result = a | (b | (c | d));
+};
+
+// These tests should fail if we bailed out to the beginning of the full
+// code.
+Test.prototype.test8 = function () {
+ // If this.x = 1 and a = 1.1:
+ this.y = this.x | b; // Should be (1 | 2) == 3.
+ this.x = c; // Should be 4.
+ this.z = this.x | a; // Should be (4 | 1.1) == 5.
+};
+
+Test.prototype.test9 = function() {
+ // If this.x = 2 and a = 1.1:
+ this.z = // (14 | 1.1) == 15
+ (this.x = // (6 | 8) == 14
+ (this.y = // (2 | 4) == 6
+ this.x // 2
+ | c) // 4
+ | d) // 8
+ | a; // 1.1
+}
+
+var t = new Test();
+
+t.test0();
+assertEquals(3, t.result);
+
+t.test1();
+assertEquals(7, t.result);
+t.test2();
+assertEquals(7, t.result);
+
+t.test3();
+assertEquals(15, t.result);
+t.test4();
+assertEquals(15, t.result);
+t.test5();
+assertEquals(15, t.result);
+t.test6();
+assertEquals(15, t.result);
+t.test7();
+assertEquals(15, t.result);
+
+a = 1.1;
+t.x = 1;
+t.test8();
+assertEquals(4, t.x);
+assertEquals(3, t.y);
+assertEquals(5, t.z);
+
+t.x = 2;
+t.test9();
+assertEquals(14, t.x);
+assertEquals(6, t.y);
+assertEquals(15, t.z);
diff --git a/test/mjsunit/compiler/simple-binary-op.js b/test/mjsunit/compiler/simple-binary-op.js
new file mode 100644
index 0000000..15e1a55
--- /dev/null
+++ b/test/mjsunit/compiler/simple-binary-op.js
@@ -0,0 +1,40 @@
+// 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: --fast-compiler
+
+var a = 1;
+var b = 2;
+var c = 4;
+
+function f() { this.x = this.x | a | b | c | a | c; }
+
+var o = {x:0, g:f}
+
+o.g();
+
+assertEquals(7, o.x);
diff --git a/test/mjsunit/compiler/simple-global-access.js b/test/mjsunit/compiler/simple-global-access.js
new file mode 100644
index 0000000..35746ba
--- /dev/null
+++ b/test/mjsunit/compiler/simple-global-access.js
@@ -0,0 +1,53 @@
+// 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: --fast-compiler
+
+// Test global variable loads with the fast compiler.
+var g1 = 42;
+var g2 = 43;
+var g3 = 44;
+this.__defineGetter__("g4", function () { return 45; });
+
+function f1() { this.x = this.y = this.z = g1; }
+function f2() { this.x = g1; this.y = g2; this.z = g3; }
+function f3() { this.x = g4; }
+
+var o = { x:0, y:0, z:0, test1:f1, test2:f2, test3:f3 }
+
+o.test1();
+assertEquals(42, o.x);
+assertEquals(42, o.y);
+assertEquals(42, o.z);
+
+o.test2();
+assertEquals(42, o.x);
+assertEquals(43, o.y);
+assertEquals(44, o.z);
+
+o.test3();
+assertEquals(45, o.x);
diff --git a/test/mjsunit/compiler/this-property-refs.js b/test/mjsunit/compiler/this-property-refs.js
new file mode 100644
index 0000000..5e8ea59
--- /dev/null
+++ b/test/mjsunit/compiler/this-property-refs.js
@@ -0,0 +1,64 @@
+// 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: --fast-compiler
+
+// Test references to properties of this.
+function Test() {
+ this.a = 0;
+ this.b = 1;
+ this.c = 2;
+ this.d = 3;
+}
+
+Test.prototype.test0 = function () {
+ this.a = this.b;
+};
+
+Test.prototype.test1 = function() {
+ this.a = this.b = this.c;
+};
+
+Test.prototype.test2 = function() {
+ this.c = this.d;
+ this.b = this.c;
+ this.a = this.b;
+};
+
+var t = new Test();
+
+t.test0();
+assertEquals(1, t.a);
+
+t.test1();
+assertEquals(2, t.a);
+assertEquals(2, t.b);
+
+t.test2();
+assertEquals(3, t.a);
+assertEquals(3, t.b);
+assertEquals(3, t.c);
diff --git a/test/mjsunit/debug-compile-event.js b/test/mjsunit/debug-compile-event.js
index 071183b..e7ecf47 100644
--- a/test/mjsunit/debug-compile-event.js
+++ b/test/mjsunit/debug-compile-event.js
@@ -90,6 +90,11 @@
var json = event_data.toJSONProtocol();
var msg = eval('(' + json + ')');
assertTrue('context' in msg.body.script);
+
+ // Check that we pick script name from //@ sourceURL, iff present
+ assertEquals(current_source.indexOf('sourceURL') >= 0 ?
+ 'myscript.js' : undefined,
+ event_data.script().name());
}
} catch (e) {
exception = e
@@ -109,6 +114,7 @@
source_count += 2; // Using eval causes additional compilation event.
compileSource('JSON.parse(\'{"a":1,"b":2}\')');
source_count++; // Using JSON.parse causes additional compilation event.
+compileSource('x=1; //@ sourceURL=myscript.js');
// Make sure that the debug event listener was invoked.
assertFalse(exception, "exception in listener")
diff --git a/test/mjsunit/debug-evaluate.js b/test/mjsunit/debug-evaluate.js
index c477907..182e2ac 100644
--- a/test/mjsunit/debug-evaluate.js
+++ b/test/mjsunit/debug-evaluate.js
@@ -87,6 +87,37 @@
testRequest(dcp, '{"expression":"a","global":true}', true, 1);
testRequest(dcp, '{"expression":"this.a","global":true}', true, 1);
+ // Test that the whole string text is returned if maxStringLength
+ // parameter is passed.
+ testRequest(
+ dcp,
+ '{"expression":"this.longString","global":true,maxStringLength:-1}',
+ true,
+ longString);
+ testRequest(
+ dcp,
+ '{"expression":"this.longString","global":true,maxStringLength:' +
+ longString.length + '}',
+ true,
+ longString);
+ var truncatedStringSuffix = '... (length: ' + longString.length + ')';
+ testRequest(
+ dcp,
+ '{"expression":"this.longString","global":true,maxStringLength:0}',
+ true,
+ truncatedStringSuffix);
+ testRequest(
+ dcp,
+ '{"expression":"this.longString","global":true,maxStringLength:1}',
+ true,
+ longString.charAt(0) + truncatedStringSuffix);
+ // Test that by default string is truncated to first 80 chars.
+ testRequest(
+ dcp,
+ '{"expression":"this.longString","global":true}',
+ true,
+ longString.substring(0, 80) + truncatedStringSuffix);
+
// Indicate that all was processed.
listenerComplete = true;
}
@@ -109,6 +140,12 @@
a = 1;
+// String which is longer than 80 chars.
+var longString = "1234567890_";
+for (var i = 0; i < 4; i++) {
+ longString += longString;
+}
+
// Set a break point at return in f and invoke g to hit the breakpoint.
Debug.setBreakPoint(f, 2, 0);
g();
diff --git a/test/mjsunit/div-mod.js b/test/mjsunit/div-mod.js
index b3c77e1..1d352b5 100644
--- a/test/mjsunit/div-mod.js
+++ b/test/mjsunit/div-mod.js
@@ -154,4 +154,18 @@
doTest(-a,-b);
}
}
-})()
+})();
+
+
+(function () {
+ // Edge cases
+ var zero = 0;
+ var minsmi32 = -0x40000000;
+ var minsmi64 = -0x80000000;
+ var somenum = 3532;
+ assertEquals(-0, zero / -1, "0 / -1");
+ assertEquals(1, minsmi32 / -0x40000000, "minsmi/minsmi-32");
+ assertEquals(1, minsmi64 / -0x80000000, "minsmi/minsmi-64");
+ assertEquals(somenum, somenum % -0x40000000, "%minsmi-32");
+ assertEquals(somenum, somenum % -0x80000000, "%minsmi-64");
+})();
diff --git a/test/mjsunit/fuzz-natives.js b/test/mjsunit/fuzz-natives.js
index d906eb8..e2f601e 100644
--- a/test/mjsunit/fuzz-natives.js
+++ b/test/mjsunit/fuzz-natives.js
@@ -27,6 +27,9 @@
// Flags: --allow-natives-syntax
+var RUN_WITH_ALL_ARGUMENT_ENTRIES = false;
+var kOnManyArgumentsRemove = 5;
+
function makeArguments() {
var result = [ ];
result.push(17);
@@ -74,13 +77,23 @@
var func = makeFunction(name, argc);
while (hasMore) {
var argPool = makeArguments();
+ // When we have 5 or more arguments we lower the amount of tests cases
+ // by randomly removing kOnManyArgumentsRemove entries
+ var numArguments = RUN_WITH_ALL_ARGUMENT_ENTRIES ?
+ kArgObjects : kArgObjects-kOnManyArgumentsRemove;
+ if (argc >= 5 && !RUN_WITH_ALL_ARGUMENT_ENTRIES) {
+ for (var i = 0; i < kOnManyArgumentsRemove; i++) {
+ var rand = Math.floor(Math.random() * (kArgObjects - i));
+ argPool.splice(rand,1);
+ }
+ }
var current = type;
var hasMore = false;
var argList = [ ];
for (var i = 0; i < argc; i++) {
- var index = current % kArgObjects;
- current = (current / kArgObjects) << 0;
- if (index != (kArgObjects - 1))
+ var index = current % numArguments;
+ current = (current / numArguments) << 0;
+ if (index != (numArguments - 1))
hasMore = true;
argList.push(argPool[index]);
}
diff --git a/test/mjsunit/object-define-properties.js b/test/mjsunit/object-define-properties.js
new file mode 100644
index 0000000..6b3725b
--- /dev/null
+++ b/test/mjsunit/object-define-properties.js
@@ -0,0 +1,56 @@
+// 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.
+
+// Tests the Object.defineProperties method - ES 15.2.3.7
+// Note that the internal DefineOwnProperty method is tested through
+// object-define-property.js, this file only contains tests specific for
+// Object.defineProperties. Also note that object-create.js contains
+// a range of indirect tests on this method since Object.create uses
+// Object.defineProperties as a step in setting up the object.
+
+// Try defining with null as descriptor:
+try {
+ Object.defineProperties({}, null);
+} catch(e) {
+ assertTrue(/null to object/.test(e));
+}
+
+// Try defining with null as object
+try {
+ Object.defineProperties(null, {});
+} catch(e) {
+ assertTrue(/called on non-object/.test(e));
+}
+
+
+var desc = {foo: {value: 10}, bar: {get: function() {return 42; }}};
+var obj = {};
+// Check that we actually get the object back as returnvalue
+var x = Object.defineProperties(obj, desc);
+
+assertEquals(x.foo, 10);
+assertEquals(x.bar, 42);
diff --git a/test/mjsunit/object-define-property.js b/test/mjsunit/object-define-property.js
new file mode 100644
index 0000000..43b1c7f
--- /dev/null
+++ b/test/mjsunit/object-define-property.js
@@ -0,0 +1,499 @@
+// 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.
+
+// Tests the object.defineProperty method - ES 15.2.3.6
+
+// Flags: --allow-natives-syntax
+
+// Check that an exception is thrown when null is passed as object.
+try {
+ Object.defineProperty(null, null, null);
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/called on non-object/.test(e));
+}
+
+// Check that an exception is thrown when undefined is passed as object.
+try {
+ Object.defineProperty(undefined, undefined, undefined);
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/called on non-object/.test(e));
+}
+
+// Check that an exception is thrown when non-object is passed as object.
+try {
+ Object.defineProperty(0, "foo", undefined);
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/called on non-object/.test(e));
+}
+
+// Object
+var obj1 = {};
+
+// Values
+var val1 = 0;
+var val2 = 0;
+var val3 = 0;
+
+// Descriptors
+var emptyDesc = {};
+
+var accessorConfigurable = {
+ set: function() { val1++; },
+ get: function() { return val1; },
+ configurable: true
+};
+
+var accessorNoConfigurable = {
+ set: function() { val2++; },
+ get: function() { return val2; },
+ configurable: false
+};
+
+var accessorOnlySet = {
+ set: function() { val3++; },
+ configurable: true
+};
+
+var accessorOnlyGet = {
+ get: function() { return val3; },
+ configurable: true
+};
+
+var accessorDefault = {set: function(){} };
+
+var dataConfigurable = { value: 1000, configurable: true };
+
+var dataNoConfigurable = { value: 2000, configurable: false };
+
+var dataWritable = { value: 3000, writable: true};
+
+
+// Check that we can't add property with undefined attributes.
+try {
+ Object.defineProperty(obj1, "foo", undefined);
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/must be an object/.test(e));
+}
+
+// Make sure that we can add a property with an empty descriptor and
+// that it has the default descriptor values.
+Object.defineProperty(obj1, "foo", emptyDesc);
+
+// foo should be undefined as it has no get, set or value
+assertEquals(undefined, obj1.foo);
+
+// We should, however, be able to retrieve the propertydescriptor which should
+// have all default values (according to 8.6.1).
+var desc = Object.getOwnPropertyDescriptor(obj1, "foo");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertFalse(desc.writable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+assertEquals(desc.value, undefined);
+
+// Make sure that getOwnPropertyDescriptor does not return a descriptor
+// with default values if called with non existing property (otherwise
+// the test above is invalid).
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertEquals(desc, undefined);
+
+// Make sure that foo can't be reset (as configurable is false).
+try {
+ Object.defineProperty(obj1, "foo", accessorConfigurable);
+} catch (e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+
+// Accessor properties
+
+Object.defineProperty(obj1, "bar", accessorConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.bar = 1);
+assertEquals(1, val1);
+assertEquals(1, obj1.bar = 1);
+assertEquals(2, val1);
+assertEquals(2, obj1.bar);
+
+// Redefine bar with non configurable test
+Object.defineProperty(obj1, "bar", accessorNoConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorNoConfigurable.get);
+assertEquals(desc.set, accessorNoConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.bar = 1);
+assertEquals(2, val1);
+assertEquals(1, val2);
+assertEquals(1, obj1.bar = 1)
+assertEquals(2, val1);
+assertEquals(2, val2);
+assertEquals(2, obj1.bar);
+
+// Try to redefine bar again - should fail as configurable is false.
+try {
+ Object.defineProperty(obj1, "bar", accessorConfigurable);
+ assertTrue(false);
+} catch(e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+// Try to redefine bar again using the data descriptor - should fail.
+try {
+ Object.defineProperty(obj1, "bar", dataConfigurable);
+ assertTrue(false);
+} catch(e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+// Redefine using same descriptor - should succeed.
+Object.defineProperty(obj1, "bar", accessorNoConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj1, "bar");
+assertFalse(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorNoConfigurable.get);
+assertEquals(desc.set, accessorNoConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.bar = 1);
+assertEquals(2, val1);
+assertEquals(3, val2);
+assertEquals(1, obj1.bar = 1)
+assertEquals(2, val1);
+assertEquals(4, val2);
+assertEquals(4, obj1.bar);
+
+// Define an accessor that has only a setter
+Object.defineProperty(obj1, "setOnly", accessorOnlySet);
+desc = Object.getOwnPropertyDescriptor(obj1, "setOnly");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.set, accessorOnlySet.set);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.value, undefined);
+assertEquals(desc.get, undefined);
+assertEquals(1, obj1.setOnly = 1);
+assertEquals(1, val3);
+
+// Add a getter - should not touch the setter
+Object.defineProperty(obj1, "setOnly", accessorOnlyGet);
+desc = Object.getOwnPropertyDescriptor(obj1, "setOnly");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, accessorOnlyGet.get);
+assertEquals(desc.set, accessorOnlySet.set);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.setOnly = 1);
+assertEquals(2, val3);
+
+// The above should also work if redefining just a getter or setter on
+// an existing property with both a getter and a setter.
+Object.defineProperty(obj1, "both", accessorConfigurable);
+
+Object.defineProperty(obj1, "both", accessorOnlySet);
+desc = Object.getOwnPropertyDescriptor(obj1, "both");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.set, accessorOnlySet.set);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj1.both = 1);
+assertEquals(3, val3);
+
+
+// Data properties
+
+Object.defineProperty(obj1, "foobar", dataConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+//Try writing to non writable attribute - should remain 1000
+obj1.foobar = 1001;
+assertEquals(obj1.foobar, 1000);
+
+
+// Redefine to writable descriptor - now writing to foobar should be allowed
+Object.defineProperty(obj1, "foobar", dataWritable);
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 3000);
+assertEquals(desc.value, 3000);
+// Note that since dataWritable does not define configurable the configurable
+// setting from the redefined property (in this case true) is used.
+assertTrue(desc.configurable);
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+// Writing to the property should now be allowed
+obj1.foobar = 1001;
+assertEquals(obj1.foobar, 1001);
+
+
+// Redefine with non configurable data property.
+Object.defineProperty(obj1, "foobar", dataNoConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 2000);
+assertEquals(desc.value, 2000);
+assertFalse(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+// Try redefine again - shold fail because configurable is now false.
+try {
+ Object.defineProperty(obj1, "foobar", dataConfigurable);
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+// Try redefine again with accessor property - shold also fail.
+try {
+ Object.defineProperty(obj1, "foobar", dataConfigurable);
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/Cannot redefine property/.test(e));
+}
+
+
+// Redifine with the same descriptor - should succeed (step 6).
+Object.defineProperty(obj1, "foobar", dataNoConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
+assertEquals(obj1.foobar, 2000);
+assertEquals(desc.value, 2000);
+assertFalse(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+// New object
+var obj2 = {};
+
+// Make accessor - redefine to data
+Object.defineProperty(obj2, "foo", accessorConfigurable);
+
+// Redefine to data property
+Object.defineProperty(obj2, "foo", dataConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj2, "foo");
+assertEquals(obj2.foo, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+// Redefine back to accessor
+Object.defineProperty(obj2, "foo", accessorConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj2, "foo");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj2.foo = 1);
+assertEquals(3, val1);
+assertEquals(4, val2);
+assertEquals(3, obj2.foo);
+
+// Make data - redefine to accessor
+Object.defineProperty(obj2, "bar", dataConfigurable)
+
+// Redefine to accessor property
+Object.defineProperty(obj2, "bar", accessorConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj2, "bar");
+assertTrue(desc.configurable);
+assertFalse(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj2.bar = 1);
+assertEquals(4, val1);
+assertEquals(4, val2);
+assertEquals(4, obj2.foo);
+
+// Redefine back to data property
+Object.defineProperty(obj2, "bar", dataConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj2, "bar");
+assertEquals(obj2.bar, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+// Redefinition of an accessor defined using __defineGetter__ and
+// __defineSetter__
+function get(){return this.x}
+function set(x){this.x=x};
+
+var obj3 = {x:1000};
+obj3.__defineGetter__("foo", get);
+obj3.__defineSetter__("foo", set);
+
+desc = Object.getOwnPropertyDescriptor(obj3, "foo");
+assertTrue(desc.configurable);
+assertTrue(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, get);
+assertEquals(desc.set, set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj3.foo = 1);
+assertEquals(1, obj3.x);
+assertEquals(1, obj3.foo);
+
+// Redefine to accessor property (non configurable) - note that enumerable
+// which we do not redefine should remain the same (true).
+Object.defineProperty(obj3, "foo", accessorNoConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj3, "foo");
+assertFalse(desc.configurable);
+assertTrue(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorNoConfigurable.get);
+assertEquals(desc.set, accessorNoConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj3.foo = 1);
+assertEquals(5, val2);
+assertEquals(5, obj3.foo);
+
+
+obj3.__defineGetter__("bar", get);
+obj3.__defineSetter__("bar", set);
+
+
+// Redefine back to data property
+Object.defineProperty(obj3, "bar", dataConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj3, "bar");
+assertEquals(obj3.bar, 1000);
+assertEquals(desc.value, 1000);
+assertTrue(desc.configurable);
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertEquals(desc.get, undefined);
+assertEquals(desc.set, undefined);
+
+
+var obj4 = {};
+var func = function (){return 42;};
+obj4.bar = func;
+assertEquals(42, obj4.bar());
+
+Object.defineProperty(obj4, "bar", accessorConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj4, "bar");
+assertTrue(desc.configurable);
+assertTrue(desc.enumerable);
+assertEquals(desc.writable, undefined);
+assertEquals(desc.get, accessorConfigurable.get);
+assertEquals(desc.set, accessorConfigurable.set);
+assertEquals(desc.value, undefined);
+assertEquals(1, obj4.bar = 1);
+assertEquals(5, val1);
+assertEquals(5, obj4.bar);
+
+// Make sure an error is thrown when trying to access to redefined function
+try {
+ obj4.bar();
+ assertTrue(false);
+} catch (e) {
+ assertTrue(/is not a function/.test(e));
+}
+
+
+// Test runtime calls to DefineOrRedefineDataProperty and
+// DefineOrRedefineAccessorProperty - make sure we don't
+// crash
+try {
+ %DefineOrRedefineAccessorProperty(0, 0, 0, 0, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineOrRedefineDataProperty(0, 0, 0, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineOrRedefineDataProperty(null, null, null, null);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineOrRedefineAccessorProperty(null, null, null, null, null);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineOrRedefineDataProperty({}, null, null, null);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+// Defining properties null should fail even when we have
+// other allowed values
+try {
+ %DefineOrRedefineAccessorProperty(null, 'foo', 0, func, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
+
+try {
+ %DefineOrRedefineDataProperty(null, 'foo', 0, 0);
+} catch (e) {
+ assertTrue(/illegal access/.test(e));
+}
diff --git a/test/mjsunit/object-get-own-property-names.js b/test/mjsunit/object-get-own-property-names.js
index f52cee2..33aa85e 100644
--- a/test/mjsunit/object-get-own-property-names.js
+++ b/test/mjsunit/object-get-own-property-names.js
@@ -57,6 +57,8 @@
assertEquals(3, propertyNames.length);
assertEquals("0", propertyNames[0]);
assertEquals("1", propertyNames[1]);
+assertEquals("string", typeof propertyNames[0]);
+assertEquals("string", typeof propertyNames[1]);
assertEquals("length", propertyNames[2]);
// Check that no proto properties are returned.
diff --git a/test/mjsunit/regress/regress-603.js b/test/mjsunit/regress/regress-603.js
new file mode 100644
index 0000000..7d4c322
--- /dev/null
+++ b/test/mjsunit/regress/regress-603.js
@@ -0,0 +1,49 @@
+// 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.
+
+// Calling non-objects directly or via Function.prototype.call should
+// not mess up the stack.
+// http://code.google.com/p/v8/issues/detail?id=603
+
+function test0() {
+ var re = /b../;
+ return re('abcdefghijklm') + 'z';
+}
+assertEquals('bcdz', test0());
+
+var re1 = /c../;
+re1.call = Function.prototype.call;
+var test1 = re1.call(null, 'abcdefghijklm') + 'z';
+assertEquals('cdez', test1);
+
+var re2 = /d../;
+var test2 = Function.prototype.call.call(re2, null, 'abcdefghijklm') + 'z';
+assertEquals('defz', test2);
+
+var re3 = /e../;
+var test3 = Function.prototype.call.apply(re3, [null, 'abcdefghijklm']) + 'z';
+assertEquals('efgz', test3);
diff --git a/test/mjsunit/regress/regress-612.js b/test/mjsunit/regress/regress-612.js
new file mode 100644
index 0000000..aee6d53
--- /dev/null
+++ b/test/mjsunit/regress/regress-612.js
@@ -0,0 +1,44 @@
+// 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.
+
+// Tests intercation between __defineGetter__/__defineSetter and fast and slow
+// mode of the objects due to series of assignments optimization.
+// (See http://code.google.com/p/v8/issues/detail?id=612)
+
+obj = {}
+
+// Define getter which currently moves object into slow mode.
+obj.__defineGetter__('foobar', function() { return 42; })
+
+// Starts initialization block mode. And turns object into slow mode.
+obj.a = 1
+obj.b = 2;
+obj.c = 3;
+// Now object is turned into fast mode, but it has getter defined above...
+
+// Now assert is triggered.
+obj.__defineGetter__('foobar', function() { return 42; })
diff --git a/test/mjsunit/setter-on-constructor-prototype.js b/test/mjsunit/setter-on-constructor-prototype.js
new file mode 100644
index 0000000..d5718f9
--- /dev/null
+++ b/test/mjsunit/setter-on-constructor-prototype.js
@@ -0,0 +1,111 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function RunTest(ensure_fast_case) {
+ function C1() {
+ this.x = 23;
+ };
+ C1.prototype = { set x(value) { this.y = 23; } };
+ if (ensure_fast_case) {
+ %ToFastProperties(C1.prototype);
+ }
+
+ for (var i = 0; i < 10; i++) {
+ var c1 = new C1();
+ assertEquals("undefined", typeof c1.x);
+ assertEquals(23, c1.y);
+ }
+
+
+ function C2() {
+ this.x = 23;
+ };
+ C2.prototype = { };
+ C2.prototype.__proto__ = { set x(value) { this.y = 23; } };
+ if (ensure_fast_case) {
+ %ToFastProperties(C2.prototype.__proto__)
+ }
+
+ for (var i = 0; i < 10; i++) {
+ var c2 = new C2();
+ assertEquals("undefined", typeof c2.x);
+ assertEquals(23, c2.y);
+ }
+
+
+ function C3() {
+ this.x = 23;
+ };
+ C3.prototype = { };
+ C3.prototype.__defineSetter__('x', function(value) { this.y = 23; });
+ if (ensure_fast_case) {
+ %ToFastProperties(C3.prototype);
+ }
+
+ for (var i = 0; i < 10; i++) {
+ var c3 = new C3();
+ assertEquals("undefined", typeof c3.x);
+ assertEquals(23, c3.y);
+ }
+
+
+ function C4() {
+ this.x = 23;
+ };
+ C4.prototype = { };
+ C4.prototype.__proto__ = { };
+ C4.prototype.__proto__.__defineSetter__('x', function(value) { this.y = 23; });
+ if (ensure_fast_case) {
+ %ToFastProperties(C4.prototype.__proto__);
+ }
+
+ for (var i = 0; i < 10; i++) {
+ var c4 = new C4();
+ assertEquals("undefined", typeof c4.x);
+ assertEquals(23, c4.y);
+ }
+
+
+ function D() {
+ this.x = 23;
+ };
+ D.prototype = 1;
+ if (ensure_fast_case) {
+ %ToFastProperties(D.prototype);
+ }
+
+ for (var i = 0; i < 10; i++) {
+ var d = new D();
+ assertEquals(23, d.x);
+ assertEquals("undefined", typeof d.y);
+ }
+}
+
+RunTest(false);
+RunTest(true);
diff --git a/test/mjsunit/substr.js b/test/mjsunit/substr.js
old mode 100644
new mode 100755
diff --git a/test/mjsunit/tools/tickprocessor-test-func-info.log b/test/mjsunit/tools/tickprocessor-test-func-info.log
new file mode 100644
index 0000000..29a12f6
--- /dev/null
+++ b/test/mjsunit/tools/tickprocessor-test-func-info.log
@@ -0,0 +1,13 @@
+shared-library,"shell",0x08048000,0x081ee000
+shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
+shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
+profiler,"begin",1
+code-creation,Stub,0x424260,348,"CompareStub_GE"
+code-creation,LazyCompile,0x2a8100,18535,"DrawQube 3d-cube.js:188"
+function-creation,0x2d11b8,0x2a8100
+code-creation,LazyCompile,0x480100,3908,"DrawLine 3d-cube.js:17"
+function-creation,0x2d0f7c,0x480100
+tick,0x424284,0xbfffeea0,0x2d0f7c,0,0x2aaaa5
+tick,0x42429f,0xbfffed88,0x2d0f7c,0,0x2aacb4
+tick,0x48063d,0xbfffec7c,0x2d0f7c,0,0x2aaec6
+profiler,"end"