| Index: test/cctest/test-api.cc
 | 
| diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
 | 
| index 8a1e9147369fbde7d20e996c91e45089c0545e67..5cd9dd45d5adfd36e76a7feea44351dfe18b3f32 100644
 | 
| --- a/test/cctest/test-api.cc
 | 
| +++ b/test/cctest/test-api.cc
 | 
| @@ -16593,3 +16593,175 @@ TEST(StringEmpty) {
 | 
|    CHECK(v8::String::Empty(isolate).IsEmpty());
 | 
|    CHECK_EQ(3, fatal_error_callback_counter);
 | 
|  }
 | 
| +
 | 
| +
 | 
| +static int instance_checked_getter_count = 0;
 | 
| +static Handle<Value> InstanceCheckedGetter(Local<String> name,
 | 
| +                                           const AccessorInfo& info) {
 | 
| +  CHECK_EQ(name, v8_str("foo"));
 | 
| +  instance_checked_getter_count++;
 | 
| +  return v8_num(11);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static int instance_checked_setter_count = 0;
 | 
| +static void InstanceCheckedSetter(Local<String> name,
 | 
| +                      Local<Value> value,
 | 
| +                      const AccessorInfo& info) {
 | 
| +  CHECK_EQ(name, v8_str("foo"));
 | 
| +  CHECK_EQ(value, v8_num(23));
 | 
| +  instance_checked_setter_count++;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static void CheckInstanceCheckedResult(int getters,
 | 
| +                                       int setters,
 | 
| +                                       bool expects_callbacks,
 | 
| +                                       TryCatch* try_catch) {
 | 
| +  if (expects_callbacks) {
 | 
| +    CHECK(!try_catch->HasCaught());
 | 
| +    CHECK_EQ(getters, instance_checked_getter_count);
 | 
| +    CHECK_EQ(setters, instance_checked_setter_count);
 | 
| +  } else {
 | 
| +    CHECK(try_catch->HasCaught());
 | 
| +    CHECK_EQ(0, instance_checked_getter_count);
 | 
| +    CHECK_EQ(0, instance_checked_setter_count);
 | 
| +  }
 | 
| +  try_catch->Reset();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
 | 
| +  instance_checked_getter_count = 0;
 | 
| +  instance_checked_setter_count = 0;
 | 
| +  TryCatch try_catch;
 | 
| +
 | 
| +  // Test path through generic runtime code.
 | 
| +  CompileRun("obj.foo");
 | 
| +  CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
 | 
| +  CompileRun("obj.foo = 23");
 | 
| +  CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
 | 
| +
 | 
| +  // Test path through generated LoadIC and StoredIC.
 | 
| +  CompileRun("function test_get(o) { o.foo; }"
 | 
| +             "test_get(obj);");
 | 
| +  CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
 | 
| +  CompileRun("test_get(obj);");
 | 
| +  CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
 | 
| +  CompileRun("test_get(obj);");
 | 
| +  CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
 | 
| +  CompileRun("function test_set(o) { o.foo = 23; }"
 | 
| +             "test_set(obj);");
 | 
| +  CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
 | 
| +  CompileRun("test_set(obj);");
 | 
| +  CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
 | 
| +  CompileRun("test_set(obj);");
 | 
| +  CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
 | 
| +
 | 
| +  // Test path through optimized code.
 | 
| +  CompileRun("%OptimizeFunctionOnNextCall(test_get);"
 | 
| +             "test_get(obj);");
 | 
| +  CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
 | 
| +  CompileRun("%OptimizeFunctionOnNextCall(test_set);"
 | 
| +             "test_set(obj);");
 | 
| +  CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
 | 
| +
 | 
| +  // Cleanup so that closures start out fresh in next check.
 | 
| +  CompileRun("%DeoptimizeFunction(test_get);"
 | 
| +             "%ClearFunctionTypeFeedback(test_get);"
 | 
| +             "%DeoptimizeFunction(test_set);"
 | 
| +             "%ClearFunctionTypeFeedback(test_set);");
 | 
| +}
 | 
| +
 | 
| +
 | 
| +THREADED_TEST(InstanceCheckOnInstanceAccessor) {
 | 
| +  v8::internal::FLAG_allow_natives_syntax = true;
 | 
| +  v8::HandleScope scope;
 | 
| +  LocalContext context;
 | 
| +
 | 
| +  Local<FunctionTemplate> templ = FunctionTemplate::New();
 | 
| +  Local<ObjectTemplate> inst = templ->InstanceTemplate();
 | 
| +  inst->SetAccessor(v8_str("foo"),
 | 
| +                    InstanceCheckedGetter, InstanceCheckedSetter,
 | 
| +                    Handle<Value>(),
 | 
| +                    v8::DEFAULT,
 | 
| +                    v8::None,
 | 
| +                    v8::AccessorSignature::New(templ));
 | 
| +  context->Global()->Set(v8_str("f"), templ->GetFunction());
 | 
| +
 | 
| +  printf("Testing positive ...\n");
 | 
| +  CompileRun("var obj = new f();");
 | 
| +  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(true);
 | 
| +
 | 
| +  printf("Testing negative ...\n");
 | 
| +  CompileRun("var obj = {};"
 | 
| +             "obj.__proto__ = new f();");
 | 
| +  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(false);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
 | 
| +  v8::internal::FLAG_allow_natives_syntax = true;
 | 
| +  v8::HandleScope scope;
 | 
| +  LocalContext context;
 | 
| +
 | 
| +  Local<FunctionTemplate> templ = FunctionTemplate::New();
 | 
| +  Local<ObjectTemplate> inst = templ->InstanceTemplate();
 | 
| +  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
 | 
| +  inst->SetAccessor(v8_str("foo"),
 | 
| +                    InstanceCheckedGetter, InstanceCheckedSetter,
 | 
| +                    Handle<Value>(),
 | 
| +                    v8::DEFAULT,
 | 
| +                    v8::None,
 | 
| +                    v8::AccessorSignature::New(templ));
 | 
| +  context->Global()->Set(v8_str("f"), templ->GetFunction());
 | 
| +
 | 
| +  printf("Testing positive ...\n");
 | 
| +  CompileRun("var obj = new f();");
 | 
| +  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(true);
 | 
| +
 | 
| +  printf("Testing negative ...\n");
 | 
| +  CompileRun("var obj = {};"
 | 
| +             "obj.__proto__ = new f();");
 | 
| +  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(false);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
 | 
| +  v8::internal::FLAG_allow_natives_syntax = true;
 | 
| +  v8::HandleScope scope;
 | 
| +  LocalContext context;
 | 
| +
 | 
| +  Local<FunctionTemplate> templ = FunctionTemplate::New();
 | 
| +  Local<ObjectTemplate> proto = templ->PrototypeTemplate();
 | 
| +  proto->SetAccessor(v8_str("foo"),
 | 
| +                     InstanceCheckedGetter, InstanceCheckedSetter,
 | 
| +                     Handle<Value>(),
 | 
| +                     v8::DEFAULT,
 | 
| +                     v8::None,
 | 
| +                     v8::AccessorSignature::New(templ));
 | 
| +  context->Global()->Set(v8_str("f"), templ->GetFunction());
 | 
| +
 | 
| +  printf("Testing positive ...\n");
 | 
| +  CompileRun("var obj = new f();");
 | 
| +  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(true);
 | 
| +
 | 
| +  printf("Testing negative ...\n");
 | 
| +  CompileRun("var obj = {};"
 | 
| +             "obj.__proto__ = new f();");
 | 
| +  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(false);
 | 
| +
 | 
| +  printf("Testing positive with modified prototype chain ...\n");
 | 
| +  CompileRun("var obj = new f();"
 | 
| +             "var pro = {};"
 | 
| +             "pro.__proto__ = obj.__proto__;"
 | 
| +             "obj.__proto__ = pro;");
 | 
| +  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
 | 
| +  CheckInstanceCheckedAccessors(true);
 | 
| +}
 | 
| 
 |