Update V8 to r4851 as required by WebKit r61121

Change-Id: Ib01b7c8e38d5b82b254192fc06365aa5b85780c5
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 46eaccd..9123125 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -27,6 +27,8 @@
 
 #include <limits.h>
 
+#define USE_NEW_QUERY_CALLBACKS
+
 #include "v8.h"
 
 #include "api.h"
@@ -610,6 +612,72 @@
 }
 
 
+class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
+ public:
+  static int dispose_calls;
+
+  TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
+      : TestAsciiResource(data),
+        dispose_(dispose) { }
+
+  void Dispose() {
+    ++dispose_calls;
+    if (dispose_) delete this;
+  }
+ private:
+  bool dispose_;
+};
+
+
+int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+
+
+TEST(ExternalStringWithDisposeHandling) {
+  const char* c_source = "1 + 2 * 3";
+
+  // Use a stack allocated external string resource allocated object.
+  TestAsciiResource::dispose_count = 0;
+  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+  TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source =  String::NewExternal(&res_stack);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage(false);
+    CHECK_EQ(0, TestAsciiResource::dispose_count);
+  }
+  v8::internal::CompilationCache::Clear();
+  v8::internal::Heap::CollectAllGarbage(false);
+  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
+  CHECK_EQ(0, TestAsciiResource::dispose_count);
+
+  // Use a heap allocated external string resource allocated object.
+  TestAsciiResource::dispose_count = 0;
+  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
+  TestAsciiResource* res_heap =
+      new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
+  {
+    v8::HandleScope scope;
+    LocalContext env;
+    Local<String> source =  String::NewExternal(res_heap);
+    Local<Script> script = Script::Compile(source);
+    Local<Value> value = script->Run();
+    CHECK(value->IsNumber());
+    CHECK_EQ(7, value->Int32Value());
+    v8::internal::Heap::CollectAllGarbage(false);
+    CHECK_EQ(0, TestAsciiResource::dispose_count);
+  }
+  v8::internal::CompilationCache::Clear();
+  v8::internal::Heap::CollectAllGarbage(false);
+  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
+  CHECK_EQ(1, TestAsciiResource::dispose_count);
+}
+
+
 THREADED_TEST(StringConcat) {
   {
     v8::HandleScope scope;
@@ -1120,11 +1188,11 @@
 }
 
 
-v8::Handle<v8::Boolean> CheckThisNamedPropertyQuery(Local<String> property,
+v8::Handle<v8::Integer> CheckThisNamedPropertyQuery(Local<String> property,
                                                     const AccessorInfo& info) {
   ApiTestFuzzer::Fuzz();
   CHECK(info.This()->Equals(bottom));
-  return v8::Handle<v8::Boolean>();
+  return v8::Handle<v8::Integer>();
 }
 
 
@@ -1221,13 +1289,13 @@
 }
 
 
-static v8::Handle<v8::Boolean> PrePropertyHandlerHas(Local<String> key,
-                                                     const AccessorInfo&) {
+static v8::Handle<v8::Integer> PrePropertyHandlerQuery(Local<String> key,
+                                                       const AccessorInfo&) {
   if (v8_str("pre")->Equals(key)) {
-    return v8::True();
+    return v8::Integer::New(v8::None);
   }
 
-  return v8::Handle<v8::Boolean>();  // do not intercept the call
+  return v8::Handle<v8::Integer>();  // do not intercept the call
 }
 
 
@@ -1236,7 +1304,7 @@
   v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
   desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
                                                     0,
-                                                    PrePropertyHandlerHas);
+                                                    PrePropertyHandlerQuery);
   LocalContext env(NULL, desc->InstanceTemplate());
   Script::Compile(v8_str(
       "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
@@ -6245,12 +6313,25 @@
   templ->SetAccessor(v8_str("y"), Return239);
   LocalContext context;
   context->Global()->Set(v8_str("o"), templ->NewInstance());
+
+  // Check the case when receiver and interceptor's holder
+  // are the same objects.
   v8::Handle<Value> value = CompileRun(
       "var result = 0;"
       "for (var i = 0; i < 7; i++) {"
       "  result = o.y;"
       "}");
   CHECK_EQ(239, value->Int32Value());
+
+  // Check the case when interceptor's holder is in proto chain
+  // of receiver.
+  value = CompileRun(
+      "r = { __proto__: o };"
+      "var result = 0;"
+      "for (var i = 0; i < 7; i++) {"
+      "  result = r.y;"
+      "}");
+  CHECK_EQ(239, value->Int32Value());
 }
 
 
@@ -6265,6 +6346,8 @@
   context->Global()->Set(v8_str("o"), templ_o->NewInstance());
   context->Global()->Set(v8_str("p"), templ_p->NewInstance());
 
+  // Check the case when receiver and interceptor's holder
+  // are the same objects.
   v8::Handle<Value> value = CompileRun(
       "o.__proto__ = p;"
       "var result = 0;"
@@ -6272,6 +6355,16 @@
       "  result = o.x + o.y;"
       "}");
   CHECK_EQ(239 + 42, value->Int32Value());
+
+  // Check the case when interceptor's holder is in proto chain
+  // of receiver.
+  value = CompileRun(
+      "r = { __proto__: o };"
+      "var result = 0;"
+      "for (var i = 0; i < 7; i++) {"
+      "  result = r.x + r.y;"
+      "}");
+  CHECK_EQ(239 + 42, value->Int32Value());
 }
 
 
@@ -7051,6 +7144,163 @@
 }
 
 
+v8::Handle<Value> keyed_call_ic_function;
+
+static v8::Handle<Value> InterceptorKeyedCallICGetter(
+    Local<String> name, const AccessorInfo& info) {
+  ApiTestFuzzer::Fuzz();
+  if (v8_str("x")->Equals(name)) {
+    return keyed_call_ic_function;
+  }
+  return v8::Handle<Value>();
+}
+
+
+// Test the case when we stored cacheable lookup into
+// a stub, but the function name changed (to another cacheable function).
+THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "proto = new Object();"
+    "proto.y = function(x) { return x + 1; };"
+    "proto.z = function(x) { return x - 1; };"
+    "o.__proto__ = proto;"
+    "var result = 0;"
+    "var method = 'y';"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (i == 5) { method = 'z'; };"
+    "  result += o[method](41);"
+    "}");
+  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+
+// Test the case when we stored cacheable lookup into
+// a stub, but the function name changed (and the new function is present
+// both before and after the interceptor in the prototype chain).
+THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
+  LocalContext context;
+  context->Global()->Set(v8_str("proto1"), templ->NewInstance());
+  keyed_call_ic_function =
+      v8_compile("function f(x) { return x - 1; }; f")->Run();
+  v8::Handle<Value> value = CompileRun(
+    "o = new Object();"
+    "proto2 = new Object();"
+    "o.y = function(x) { return x + 1; };"
+    "proto2.y = function(x) { return x + 2; };"
+    "o.__proto__ = proto1;"
+    "proto1.__proto__ = proto2;"
+    "var result = 0;"
+    "var method = 'x';"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (i == 5) { method = 'y'; };"
+    "  result += o[method](41);"
+    "}");
+  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+
+// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
+// on the global object.
+THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
+  templ->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ->NewInstance());
+  v8::Handle<Value> value = CompileRun(
+    "function inc(x) { return x + 1; };"
+    "inc(1);"
+    "function dec(x) { return x - 1; };"
+    "dec(1);"
+    "o.__proto__ = this;"
+    "this.__proto__.x = inc;"
+    "this.__proto__.y = dec;"
+    "var result = 0;"
+    "var method = 'x';"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (i == 5) { method = 'y'; };"
+    "  result += o[method](41);"
+    "}");
+  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+
+// Test the case when actual function to call sits on global object.
+THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "function len(x) { return x.length; };"
+    "o.__proto__ = this;"
+    "var m = 'parseFloat';"
+    "var result = 0;"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (i == 5) {"
+    "    m = 'len';"
+    "    saved_result = result;"
+    "  };"
+    "  result = o[m]('239');"
+    "}");
+  CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
+  CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
+}
+
+// Test the map transition before the interceptor.
+THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "var o = new Object();"
+    "o.__proto__ = proto;"
+    "o.method = function(x) { return x + 1; };"
+    "var m = 'method';"
+    "var result = 0;"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (i == 5) { o.method = function(x) { return x - 1; }; };"
+    "  result += o[m](41);"
+    "}");
+  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+
+// Test the map transition after the interceptor.
+THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
+  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
+  LocalContext context;
+  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
+
+  v8::Handle<Value> value = CompileRun(
+    "var proto = new Object();"
+    "o.__proto__ = proto;"
+    "proto.method = function(x) { return x + 1; };"
+    "var m = 'method';"
+    "var result = 0;"
+    "for (var i = 0; i < 10; i++) {"
+    "  if (i == 5) { proto.method = function(x) { return x - 1; }; };"
+    "  result += o[m](41);"
+    "}");
+  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
+}
+
+
 static int interceptor_call_count = 0;
 
 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
@@ -7203,6 +7453,18 @@
 }
 
 
+THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+  templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
+  LocalContext env;
+  env->Global()->Set(v8_str("obj"),
+                     templ->GetFunction()->NewInstance());
+  ExpectTrue("obj.x === 42");
+  ExpectTrue("!obj.propertyIsEnumerable('x')");
+}
+
+
 static v8::Handle<Value> ParentGetter(Local<String> name,
                                       const AccessorInfo& info) {
   ApiTestFuzzer::Fuzz();
@@ -8236,6 +8498,30 @@
 }
 
 
+// Verifies that the Handle<String> and const char* versions of the API produce
+// the same results (at least for one trivial case).
+TEST(PreCompileAPIVariationsAreSame) {
+  v8::V8::Initialize();
+  v8::HandleScope scope;
+
+  const char* cstring = "function foo(a) { return a+1; }";
+  v8::ScriptData* sd_from_cstring =
+      v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
+
+  TestAsciiResource* resource = new TestAsciiResource(cstring);
+  v8::ScriptData* sd_from_istring = v8::ScriptData::PreCompile(
+      v8::String::NewExternal(resource));
+
+  CHECK_EQ(sd_from_cstring->Length(), sd_from_istring->Length());
+  CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
+                     sd_from_istring->Data(),
+                     sd_from_cstring->Length()));
+
+  delete sd_from_cstring;
+  delete sd_from_istring;
+}
+
+
 // This tests that we do not allow dictionary load/call inline caches
 // to use functions that have not yet been compiled.  The potential
 // problem of loading a function that has not yet been compiled can