OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1821 for (i = 0; name_str[i] && prefix[i]; ++i) { | 1821 for (i = 0; name_str[i] && prefix[i]; ++i) { |
1822 if (name_str[i] != prefix[i]) return; | 1822 if (name_str[i] != prefix[i]) return; |
1823 } | 1823 } |
1824 Handle<Object> self = info.This(); | 1824 Handle<Object> self = info.This(); |
1825 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i))); | 1825 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i))); |
1826 } | 1826 } |
1827 | 1827 |
1828 void InterceptorSetter(Local<String> name, | 1828 void InterceptorSetter(Local<String> name, |
1829 Local<Value> value, | 1829 Local<Value> value, |
1830 const v8::PropertyCallbackInfo<v8::Value>& info) { | 1830 const v8::PropertyCallbackInfo<v8::Value>& info) { |
1831 // Intercept accesses that set certain integer values. | 1831 // Intercept accesses that set certain integer values, for which the name does |
| 1832 // not start with 'accessor_'. |
| 1833 String::Utf8Value utf8(name); |
| 1834 char* name_str = *utf8; |
| 1835 char prefix[] = "accessor_"; |
| 1836 int i; |
| 1837 for (i = 0; name_str[i] && prefix[i]; ++i) { |
| 1838 if (name_str[i] != prefix[i]) break; |
| 1839 } |
| 1840 if (!prefix[i]) return; |
| 1841 |
1832 if (value->IsInt32() && value->Int32Value() < 10000) { | 1842 if (value->IsInt32() && value->Int32Value() < 10000) { |
1833 Handle<Object> self = info.This(); | 1843 Handle<Object> self = info.This(); |
1834 self->SetHiddenValue(name, value); | 1844 self->SetHiddenValue(name, value); |
1835 info.GetReturnValue().Set(value); | 1845 info.GetReturnValue().Set(value); |
1836 } | 1846 } |
1837 } | 1847 } |
1838 | 1848 |
1839 void AddAccessor(Handle<FunctionTemplate> templ, | 1849 void AddAccessor(Handle<FunctionTemplate> templ, |
1840 Handle<String> name, | 1850 Handle<String> name, |
1841 v8::AccessorGetterCallback getter, | 1851 v8::AccessorGetterCallback getter, |
(...skipping 18471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20313 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter); | 20323 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter); |
20314 context->Global()->Set(v8_str("Bug"), templ->GetFunction()); | 20324 context->Global()->Set(v8_str("Bug"), templ->GetFunction()); |
20315 CompileRun("\"use strict\"; var o = new Bug;" | 20325 CompileRun("\"use strict\"; var o = new Bug;" |
20316 "function f(o) { o.x = 10; };" | 20326 "function f(o) { o.x = 10; };" |
20317 "f(o); f(o); f(o);" | 20327 "f(o); f(o); f(o);" |
20318 "%OptimizeFunctionOnNextCall(f);" | 20328 "%OptimizeFunctionOnNextCall(f);" |
20319 "f(o);"); | 20329 "f(o);"); |
20320 ExpectBoolean("%GetOptimizationStatus(f) != 2", true); | 20330 ExpectBoolean("%GetOptimizationStatus(f) != 2", true); |
20321 } | 20331 } |
20322 | 20332 |
| 20333 |
| 20334 THREADED_TEST(CrankshaftInterceptorSetter) { |
| 20335 i::FLAG_allow_natives_syntax = true; |
| 20336 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 20337 Handle<FunctionTemplate> templ = FunctionTemplate::New(); |
| 20338 AddInterceptor(templ, InterceptorGetter, InterceptorSetter); |
| 20339 LocalContext env; |
| 20340 env->Global()->Set(v8_str("Obj"), templ->GetFunction()); |
| 20341 CompileRun("var obj = new Obj;" |
| 20342 // Initialize fields to avoid transitions later. |
| 20343 "obj.age = 0;" |
| 20344 "obj.accessor_age = 42;" |
| 20345 "function setter(i) { this.accessor_age = i; };" |
| 20346 "function getter() { return this.accessor_age; };" |
| 20347 "function setAge(i) { obj.age = i; };" |
| 20348 "Object.defineProperty(obj, 'age', { get:getter, set:setter });" |
| 20349 "setAge(1);" |
| 20350 "setAge(2);" |
| 20351 "setAge(3);" |
| 20352 "%OptimizeFunctionOnNextCall(setAge);" |
| 20353 "setAge(4);"); |
| 20354 // All stores went through the interceptor. |
| 20355 ExpectInt32("obj.interceptor_age", 4); |
| 20356 ExpectInt32("obj.accessor_age", 42); |
| 20357 } |
| 20358 |
| 20359 |
| 20360 THREADED_TEST(CrankshaftInterceptorGetter) { |
| 20361 i::FLAG_allow_natives_syntax = true; |
| 20362 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 20363 Handle<FunctionTemplate> templ = FunctionTemplate::New(); |
| 20364 AddInterceptor(templ, InterceptorGetter, InterceptorSetter); |
| 20365 LocalContext env; |
| 20366 env->Global()->Set(v8_str("Obj"), templ->GetFunction()); |
| 20367 CompileRun("var obj = new Obj;" |
| 20368 // Initialize fields to avoid transitions later. |
| 20369 "obj.age = 1;" |
| 20370 "obj.accessor_age = 42;" |
| 20371 "function getter() { return this.accessor_age; };" |
| 20372 "function getAge() { return obj.interceptor_age; };" |
| 20373 "Object.defineProperty(obj, 'interceptor_age', { get:getter });" |
| 20374 "getAge();" |
| 20375 "getAge();" |
| 20376 "getAge();" |
| 20377 "%OptimizeFunctionOnNextCall(getAge);"); |
| 20378 // Access through interceptor. |
| 20379 ExpectInt32("getAge()", 1); |
| 20380 } |
| 20381 |
| 20382 |
| 20383 THREADED_TEST(CrankshaftInterceptorFieldRead) { |
| 20384 i::FLAG_allow_natives_syntax = true; |
| 20385 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 20386 Handle<FunctionTemplate> templ = FunctionTemplate::New(); |
| 20387 AddInterceptor(templ, InterceptorGetter, InterceptorSetter); |
| 20388 LocalContext env; |
| 20389 env->Global()->Set(v8_str("Obj"), templ->GetFunction()); |
| 20390 CompileRun("var obj = new Obj;" |
| 20391 "obj.__proto__.interceptor_age = 42;" |
| 20392 "obj.age = 100;" |
| 20393 "function getAge() { return obj.interceptor_age; };"); |
| 20394 ExpectInt32("getAge();", 100); |
| 20395 ExpectInt32("getAge();", 100); |
| 20396 ExpectInt32("getAge();", 100); |
| 20397 CompileRun("%OptimizeFunctionOnNextCall(getAge);"); |
| 20398 // Access through interceptor. |
| 20399 ExpectInt32("getAge();", 100); |
| 20400 } |
| 20401 |
| 20402 |
| 20403 THREADED_TEST(CrankshaftInterceptorFieldWrite) { |
| 20404 i::FLAG_allow_natives_syntax = true; |
| 20405 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 20406 Handle<FunctionTemplate> templ = FunctionTemplate::New(); |
| 20407 AddInterceptor(templ, InterceptorGetter, InterceptorSetter); |
| 20408 LocalContext env; |
| 20409 env->Global()->Set(v8_str("Obj"), templ->GetFunction()); |
| 20410 CompileRun("var obj = new Obj;" |
| 20411 "obj.age = 100000;" |
| 20412 "function setAge(i) { obj.age = i };" |
| 20413 "setAge(100);" |
| 20414 "setAge(101);" |
| 20415 "setAge(102);" |
| 20416 "%OptimizeFunctionOnNextCall(setAge);" |
| 20417 "setAge(103);"); |
| 20418 ExpectInt32("obj.age", 100000); |
| 20419 ExpectInt32("obj.interceptor_age", 103); |
| 20420 } |
| 20421 |
20323 #endif // V8_OS_POSIX | 20422 #endif // V8_OS_POSIX |
OLD | NEW |