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 14549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14560 env->Global()->Get(v8::String::New("foo"))); | 14560 env->Global()->Get(v8::String::New("foo"))); |
14561 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast( | 14561 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast( |
14562 env->Global()->Get(v8::String::New("bar"))); | 14562 env->Global()->Get(v8::String::New("bar"))); |
14563 CHECK_EQ(script->Id(), foo->GetScriptId()); | 14563 CHECK_EQ(script->Id(), foo->GetScriptId()); |
14564 CHECK_EQ(script->Id(), bar->GetScriptId()); | 14564 CHECK_EQ(script->Id(), bar->GetScriptId()); |
14565 } | 14565 } |
14566 | 14566 |
14567 | 14567 |
14568 static v8::Handle<Value> GetterWhichReturns42(Local<String> name, | 14568 static v8::Handle<Value> GetterWhichReturns42(Local<String> name, |
14569 const AccessorInfo& info) { | 14569 const AccessorInfo& info) { |
| 14570 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject()); |
| 14571 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject()); |
14570 return v8_num(42); | 14572 return v8_num(42); |
14571 } | 14573 } |
14572 | 14574 |
14573 | 14575 |
14574 static void SetterWhichSetsYOnThisTo23(Local<String> name, | 14576 static void SetterWhichSetsYOnThisTo23(Local<String> name, |
14575 Local<Value> value, | 14577 Local<Value> value, |
14576 const AccessorInfo& info) { | 14578 const AccessorInfo& info) { |
| 14579 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject()); |
| 14580 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject()); |
14577 info.This()->Set(v8_str("y"), v8_num(23)); | 14581 info.This()->Set(v8_str("y"), v8_num(23)); |
14578 } | 14582 } |
14579 | 14583 |
14580 | 14584 |
| 14585 Handle<Value> FooGetInterceptor(Local<String> name, |
| 14586 const AccessorInfo& info) { |
| 14587 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject()); |
| 14588 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject()); |
| 14589 if (!name->Equals(v8_str("foo"))) return Handle<Value>(); |
| 14590 return v8_num(42); |
| 14591 } |
| 14592 |
| 14593 |
| 14594 Handle<Value> FooSetInterceptor(Local<String> name, |
| 14595 Local<Value> value, |
| 14596 const AccessorInfo& info) { |
| 14597 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject()); |
| 14598 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject()); |
| 14599 if (!name->Equals(v8_str("foo"))) return Handle<Value>(); |
| 14600 info.This()->Set(v8_str("y"), v8_num(23)); |
| 14601 return v8_num(23); |
| 14602 } |
| 14603 |
| 14604 |
14581 TEST(SetterOnConstructorPrototype) { | 14605 TEST(SetterOnConstructorPrototype) { |
14582 v8::HandleScope scope; | 14606 v8::HandleScope scope; |
14583 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 14607 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
14584 templ->SetAccessor(v8_str("x"), | 14608 templ->SetAccessor(v8_str("x"), |
14585 GetterWhichReturns42, | 14609 GetterWhichReturns42, |
14586 SetterWhichSetsYOnThisTo23); | 14610 SetterWhichSetsYOnThisTo23); |
14587 LocalContext context; | 14611 LocalContext context; |
14588 context->Global()->Set(v8_str("P"), templ->NewInstance()); | 14612 context->Global()->Set(v8_str("P"), templ->NewInstance()); |
14589 CompileRun("function C1() {" | 14613 CompileRun("function C1() {" |
14590 " this.x = 23;" | 14614 " this.x = 23;" |
(...skipping 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16806 "} \n"; | 16830 "} \n"; |
16807 CompileRun(throw_again); | 16831 CompileRun(throw_again); |
16808 CHECK(try_catch.HasCaught()); | 16832 CHECK(try_catch.HasCaught()); |
16809 Local<Message> message = try_catch.Message(); | 16833 Local<Message> message = try_catch.Message(); |
16810 CHECK(!message.IsEmpty()); | 16834 CHECK(!message.IsEmpty()); |
16811 CHECK_EQ(6, message->GetLineNumber()); | 16835 CHECK_EQ(6, message->GetLineNumber()); |
16812 } | 16836 } |
16813 } | 16837 } |
16814 | 16838 |
16815 | 16839 |
| 16840 static void Helper137002(bool do_store, |
| 16841 bool polymorphic, |
| 16842 bool remove_accessor, |
| 16843 bool interceptor) { |
| 16844 LocalContext context; |
| 16845 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 16846 if (interceptor) { |
| 16847 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor); |
| 16848 } else { |
| 16849 templ->SetAccessor(v8_str("foo"), |
| 16850 GetterWhichReturns42, |
| 16851 SetterWhichSetsYOnThisTo23); |
| 16852 } |
| 16853 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
| 16854 |
| 16855 // Turn monomorphic on slow object with native accessor, then turn |
| 16856 // polymorphic, finally optimize to create negative lookup and fail. |
| 16857 CompileRun(do_store ? |
| 16858 "function f(x) { x.foo = void 0; }" : |
| 16859 "function f(x) { return x.foo; }"); |
| 16860 CompileRun("obj.y = void 0;"); |
| 16861 if (!interceptor) { |
| 16862 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);"); |
| 16863 } |
| 16864 CompileRun("obj.__proto__ = null;" |
| 16865 "f(obj); f(obj); f(obj);"); |
| 16866 if (polymorphic) { |
| 16867 CompileRun("f({});"); |
| 16868 } |
| 16869 CompileRun("obj.y = void 0;" |
| 16870 "%OptimizeFunctionOnNextCall(f);"); |
| 16871 if (remove_accessor) { |
| 16872 CompileRun("delete obj.foo;"); |
| 16873 } |
| 16874 CompileRun("var result = f(obj);"); |
| 16875 if (do_store) { |
| 16876 CompileRun("result = obj.y;"); |
| 16877 } |
| 16878 if (remove_accessor && !interceptor) { |
| 16879 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined()); |
| 16880 } else { |
| 16881 CHECK_EQ(do_store ? 23 : 42, |
| 16882 context->Global()->Get(v8_str("result"))->Int32Value()); |
| 16883 } |
| 16884 } |
| 16885 |
| 16886 |
16816 THREADED_TEST(Regress137002a) { | 16887 THREADED_TEST(Regress137002a) { |
16817 i::FLAG_allow_natives_syntax = true; | 16888 i::FLAG_allow_natives_syntax = true; |
| 16889 i::FLAG_compilation_cache = false; |
| 16890 v8::HandleScope scope; |
| 16891 for (int i = 0; i < 16; i++) { |
| 16892 Helper137002(i & 8, i & 4, i & 2, i & 1); |
| 16893 } |
| 16894 } |
| 16895 |
| 16896 |
| 16897 THREADED_TEST(Regress137002b) { |
| 16898 i::FLAG_allow_natives_syntax = true; |
16818 v8::HandleScope scope; | 16899 v8::HandleScope scope; |
16819 LocalContext context; | 16900 LocalContext context; |
16820 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 16901 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
16821 templ->SetAccessor(v8_str("foo"), | 16902 templ->SetAccessor(v8_str("foo"), |
16822 GetterWhichReturns42, | 16903 GetterWhichReturns42, |
16823 SetterWhichSetsYOnThisTo23); | 16904 SetterWhichSetsYOnThisTo23); |
16824 context->Global()->Set(v8_str("obj"), templ->NewInstance()); | 16905 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
16825 | 16906 |
16826 // Turn monomorphic on slow object with native accessor, then turn | 16907 // Turn monomorphic on slow object with native accessor, then just |
16827 // polymorphic, finally optimize to create negative lookup and fail. | 16908 // delete the property and fail. |
16828 CompileRun("function f(x) { return x.foo; }" | 16909 CompileRun("function load(x) { return x.foo; }" |
| 16910 "function store(x) { x.foo = void 0; }" |
| 16911 "function keyed_load(x, key) { return x[key]; }" |
| 16912 // Second version of function has a different source (add void 0) |
| 16913 // so that it does not share code with the first version. This |
| 16914 // ensures that the ICs are monomorphic. |
| 16915 "function load2(x) { void 0; return x.foo; }" |
| 16916 "function store2(x) { void 0; x.foo = void 0; }" |
| 16917 "function keyed_load2(x, key) { void 0; return x[key]; }" |
| 16918 |
| 16919 "obj.y = void 0;" |
| 16920 "obj.__proto__ = null;" |
| 16921 "var subobj = {};" |
| 16922 "subobj.y = void 0;" |
| 16923 "subobj.__proto__ = obj;" |
16829 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" | 16924 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" |
16830 "obj.__proto__ = null;" | 16925 |
16831 "f(obj); f(obj); f({});" | 16926 // Make the ICs monomorphic. |
16832 "%OptimizeFunctionOnNextCall(f);" | 16927 "load(obj); load(obj);" |
16833 "var result = f(obj);"); | 16928 "load2(subobj); load2(subobj);" |
16834 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); | 16929 "store(obj); store(obj);" |
| 16930 "store2(subobj); store2(subobj);" |
| 16931 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');" |
| 16932 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');" |
| 16933 |
| 16934 // Actually test the shiny new ICs and better not crash. This |
| 16935 // serves as a regression test for issue 142088 as well. |
| 16936 "load(obj);" |
| 16937 "load2(subobj);" |
| 16938 "store(obj);" |
| 16939 "store2(subobj);" |
| 16940 "keyed_load(obj, 'foo');" |
| 16941 "keyed_load2(subobj, 'foo');" |
| 16942 |
| 16943 // Delete the accessor. It better not be called any more now. |
| 16944 "delete obj.foo;" |
| 16945 "obj.y = void 0;" |
| 16946 "subobj.y = void 0;" |
| 16947 |
| 16948 "var load_result = load(obj);" |
| 16949 "var load_result2 = load2(subobj);" |
| 16950 "var keyed_load_result = keyed_load(obj, 'foo');" |
| 16951 "var keyed_load_result2 = keyed_load2(subobj, 'foo');" |
| 16952 "store(obj);" |
| 16953 "store2(subobj);" |
| 16954 "var y_from_obj = obj.y;" |
| 16955 "var y_from_subobj = subobj.y;"); |
| 16956 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined()); |
| 16957 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined()); |
| 16958 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined()); |
| 16959 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined()); |
| 16960 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined()); |
| 16961 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined()); |
16835 } | 16962 } |
16836 | 16963 |
16837 | 16964 |
16838 THREADED_TEST(Regress137002b) { | 16965 THREADED_TEST(Regress142088) { |
16839 i::FLAG_allow_natives_syntax = true; | 16966 i::FLAG_allow_natives_syntax = true; |
16840 v8::HandleScope scope; | 16967 v8::HandleScope scope; |
16841 LocalContext context; | 16968 LocalContext context; |
16842 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 16969 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
16843 templ->SetAccessor(v8_str("foo"), | 16970 templ->SetAccessor(v8_str("foo"), |
16844 GetterWhichReturns42, | 16971 GetterWhichReturns42, |
16845 SetterWhichSetsYOnThisTo23); | 16972 SetterWhichSetsYOnThisTo23); |
16846 context->Global()->Set(v8_str("obj"), templ->NewInstance()); | 16973 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
16847 | 16974 |
16848 // Turn monomorphic on slow object with native accessor, then just | 16975 // Turn monomorphic on slow object with native accessor, then just |
16849 // delete the property and fail. | 16976 // delete the property and fail. |
16850 CompileRun("function f(x) { return x.foo; }" | 16977 CompileRun("function load(x) { return x.foo; }" |
| 16978 "function store(x) { x.foo = void 0; }" |
| 16979 "function keyed_load(x, key) { return x[key]; }" |
| 16980 // Second version of function has a different source (add void 0) |
| 16981 // so that it does not share code with the first version. This |
| 16982 // ensures that the ICs are monomorphic. |
| 16983 "function load2(x) { void 0; return x.foo; }" |
| 16984 "function store2(x) { void 0; x.foo = void 0; }" |
| 16985 "function keyed_load2(x, key) { void 0; return x[key]; }" |
| 16986 |
| 16987 "obj.__proto__ = null;" |
| 16988 "var subobj = {};" |
| 16989 "subobj.__proto__ = obj;" |
16851 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" | 16990 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" |
16852 "obj.__proto__ = null;" | 16991 |
16853 "f(obj); f(obj); delete obj.foo;" | 16992 // Make the ICs monomorphic. |
16854 "var result = f(obj);"); | 16993 "load(obj); load(obj);" |
16855 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined()); | 16994 "load2(subobj); load2(subobj);" |
| 16995 "store(obj);" |
| 16996 "store2(subobj);" |
| 16997 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');" |
| 16998 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');" |
| 16999 |
| 17000 // Delete the accessor. It better not be called any more now. |
| 17001 "delete obj.foo;" |
| 17002 "obj.y = void 0;" |
| 17003 "subobj.y = void 0;" |
| 17004 |
| 17005 "var load_result = load(obj);" |
| 17006 "var load_result2 = load2(subobj);" |
| 17007 "var keyed_load_result = keyed_load(obj, 'foo');" |
| 17008 "var keyed_load_result2 = keyed_load2(subobj, 'foo');" |
| 17009 "store(obj);" |
| 17010 "store2(subobj);" |
| 17011 "var y_from_obj = obj.y;" |
| 17012 "var y_from_subobj = subobj.y;"); |
| 17013 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined()); |
| 17014 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined()); |
| 17015 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined()); |
| 17016 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined()); |
| 17017 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined()); |
| 17018 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined()); |
16856 } | 17019 } |
OLD | NEW |