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 14715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14726 } | 14726 } |
14727 | 14727 |
14728 | 14728 |
14729 static void SetterWhichSetsYOnThisTo23(Local<String> name, | 14729 static void SetterWhichSetsYOnThisTo23(Local<String> name, |
14730 Local<Value> value, | 14730 Local<Value> value, |
14731 const AccessorInfo& info) { | 14731 const AccessorInfo& info) { |
14732 info.This()->Set(v8_str("y"), v8_num(23)); | 14732 info.This()->Set(v8_str("y"), v8_num(23)); |
14733 } | 14733 } |
14734 | 14734 |
14735 | 14735 |
| 14736 Handle<Value> FooGetInterceptor(Local<String> name, |
| 14737 const AccessorInfo& info) { |
| 14738 if (!name->Equals(v8_str("foo"))) return Handle<Value>(); |
| 14739 return v8_num(42); |
| 14740 } |
| 14741 |
| 14742 |
| 14743 Handle<Value> FooSetInterceptor(Local<String> name, |
| 14744 Local<Value> value, |
| 14745 const AccessorInfo& info) { |
| 14746 if (!name->Equals(v8_str("foo"))) return Handle<Value>(); |
| 14747 info.This()->Set(v8_str("y"), v8_num(23)); |
| 14748 return v8_num(23); |
| 14749 } |
| 14750 |
| 14751 |
14736 TEST(SetterOnConstructorPrototype) { | 14752 TEST(SetterOnConstructorPrototype) { |
14737 v8::HandleScope scope; | 14753 v8::HandleScope scope; |
14738 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 14754 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
14739 templ->SetAccessor(v8_str("x"), | 14755 templ->SetAccessor(v8_str("x"), |
14740 GetterWhichReturns42, | 14756 GetterWhichReturns42, |
14741 SetterWhichSetsYOnThisTo23); | 14757 SetterWhichSetsYOnThisTo23); |
14742 LocalContext context; | 14758 LocalContext context; |
14743 context->Global()->Set(v8_str("P"), templ->NewInstance()); | 14759 context->Global()->Set(v8_str("P"), templ->NewInstance()); |
14744 CompileRun("function C1() {" | 14760 CompileRun("function C1() {" |
14745 " this.x = 23;" | 14761 " this.x = 23;" |
(...skipping 2216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16962 "} \n"; | 16978 "} \n"; |
16963 CompileRun(throw_again); | 16979 CompileRun(throw_again); |
16964 CHECK(try_catch.HasCaught()); | 16980 CHECK(try_catch.HasCaught()); |
16965 Local<Message> message = try_catch.Message(); | 16981 Local<Message> message = try_catch.Message(); |
16966 CHECK(!message.IsEmpty()); | 16982 CHECK(!message.IsEmpty()); |
16967 CHECK_EQ(6, message->GetLineNumber()); | 16983 CHECK_EQ(6, message->GetLineNumber()); |
16968 } | 16984 } |
16969 } | 16985 } |
16970 | 16986 |
16971 | 16987 |
| 16988 static void Helper137002(bool do_store, |
| 16989 bool polymorphic, |
| 16990 bool remove_accessor, |
| 16991 bool interceptor) { |
| 16992 LocalContext context; |
| 16993 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 16994 if (interceptor) { |
| 16995 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor); |
| 16996 } else { |
| 16997 templ->SetAccessor(v8_str("foo"), |
| 16998 GetterWhichReturns42, |
| 16999 SetterWhichSetsYOnThisTo23); |
| 17000 } |
| 17001 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
| 17002 |
| 17003 // Turn monomorphic on slow object with native accessor, then turn |
| 17004 // polymorphic, finally optimize to create negative lookup and fail. |
| 17005 CompileRun(do_store ? |
| 17006 "function f(x) { x.foo = void 0; }" : |
| 17007 "function f(x) { return x.foo; }"); |
| 17008 CompileRun("obj.y = void 0;"); |
| 17009 if (!interceptor) { |
| 17010 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);"); |
| 17011 } |
| 17012 CompileRun("obj.__proto__ = null;" |
| 17013 "f(obj); f(obj); f(obj);"); |
| 17014 if (polymorphic) { |
| 17015 CompileRun("f({});"); |
| 17016 } |
| 17017 CompileRun("obj.y = void 0;" |
| 17018 "%OptimizeFunctionOnNextCall(f);"); |
| 17019 if (remove_accessor) { |
| 17020 CompileRun("delete obj.foo;"); |
| 17021 } |
| 17022 CompileRun("var result = f(obj);"); |
| 17023 if (do_store) { |
| 17024 CompileRun("result = obj.y;"); |
| 17025 } |
| 17026 if (remove_accessor && !interceptor) { |
| 17027 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined()); |
| 17028 } else { |
| 17029 CHECK_EQ(do_store ? 23 : 42, |
| 17030 context->Global()->Get(v8_str("result"))->Int32Value()); |
| 17031 } |
| 17032 } |
| 17033 |
| 17034 |
16972 THREADED_TEST(Regress137002a) { | 17035 THREADED_TEST(Regress137002a) { |
16973 i::FLAG_allow_natives_syntax = true; | 17036 i::FLAG_allow_natives_syntax = true; |
| 17037 i::FLAG_compilation_cache = false; |
16974 v8::HandleScope scope; | 17038 v8::HandleScope scope; |
16975 LocalContext context; | 17039 for (int i = 0; i < 16; i++) { |
16976 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 17040 Helper137002(i & 8, i & 4, i & 2, i & 1); |
16977 templ->SetAccessor(v8_str("foo"), | 17041 } |
16978 GetterWhichReturns42, | |
16979 SetterWhichSetsYOnThisTo23); | |
16980 context->Global()->Set(v8_str("obj"), templ->NewInstance()); | |
16981 | |
16982 // Turn monomorphic on slow object with native accessor, then turn | |
16983 // polymorphic, finally optimize to create negative lookup and fail. | |
16984 CompileRun("function f(x) { return x.foo; }" | |
16985 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" | |
16986 "obj.__proto__ = null;" | |
16987 "f(obj); f(obj); f({});" | |
16988 "%OptimizeFunctionOnNextCall(f);" | |
16989 "var result = f(obj);"); | |
16990 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); | |
16991 } | 17042 } |
16992 | 17043 |
16993 | 17044 |
16994 THREADED_TEST(Regress137002b) { | 17045 THREADED_TEST(Regress137002b) { |
16995 i::FLAG_allow_natives_syntax = true; | 17046 i::FLAG_allow_natives_syntax = true; |
16996 v8::HandleScope scope; | 17047 v8::HandleScope scope; |
16997 LocalContext context; | 17048 LocalContext context; |
16998 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 17049 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
16999 templ->SetAccessor(v8_str("foo"), | 17050 templ->SetAccessor(v8_str("foo"), |
17000 GetterWhichReturns42, | 17051 GetterWhichReturns42, |
17001 SetterWhichSetsYOnThisTo23); | 17052 SetterWhichSetsYOnThisTo23); |
17002 context->Global()->Set(v8_str("obj"), templ->NewInstance()); | 17053 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
17003 | 17054 |
17004 // Turn monomorphic on slow object with native accessor, then just | 17055 // Turn monomorphic on slow object with native accessor, then just |
17005 // delete the property and fail. | 17056 // delete the property and fail. |
17006 CompileRun("function f(x) { return x.foo; }" | 17057 CompileRun("function load(x) { return x.foo; }" |
| 17058 "function store(x) { x.foo = void 0; }" |
| 17059 "function keyed_load(x, key) { return x[key]; }" |
| 17060 // Second version of function has a different source (add void 0) |
| 17061 // so that it does not share code with the first version. This |
| 17062 // ensures that the ICs are monomorphic. |
| 17063 "function load2(x) { void 0; return x.foo; }" |
| 17064 "function store2(x) { void 0; x.foo = void 0; }" |
| 17065 "function keyed_load2(x, key) { void 0; return x[key]; }" |
| 17066 |
| 17067 "obj.__proto__ = null;" |
| 17068 "var subobj = {};" |
| 17069 "subobj.__proto__ = obj;" |
17007 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" | 17070 "%OptimizeObjectForAddingMultipleProperties(obj, 1);" |
17008 "obj.__proto__ = null;" | 17071 |
17009 "f(obj); f(obj); delete obj.foo;" | 17072 // Make the ICs monomorphic. |
17010 "var result = f(obj);"); | 17073 "load(obj); load(obj);" |
17011 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined()); | 17074 "load2(subobj); load2(subobj);" |
| 17075 "store(obj);" |
| 17076 "store2(subobj);" |
| 17077 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');" |
| 17078 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');" |
| 17079 |
| 17080 // Delete the accessor. It better not be called any more now. |
| 17081 "delete obj.foo;" |
| 17082 "obj.y = void 0;" |
| 17083 "subobj.y = void 0;" |
| 17084 |
| 17085 "var load_result = load(obj);" |
| 17086 "var load_result2 = load2(subobj);" |
| 17087 "var keyed_load_result = keyed_load(obj, 'foo');" |
| 17088 "var keyed_load_result2 = keyed_load2(subobj, 'foo');" |
| 17089 "store(obj);" |
| 17090 "store2(subobj);" |
| 17091 "var y_from_obj = obj.y;" |
| 17092 "var y_from_subobj = subobj.y;"); |
| 17093 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined()); |
| 17094 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined()); |
| 17095 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined()); |
| 17096 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined()); |
| 17097 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined()); |
| 17098 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined()); |
17012 } | 17099 } |
17013 | 17100 |
17014 | 17101 |
17015 THREADED_TEST(Regress137496) { | 17102 THREADED_TEST(Regress137496) { |
17016 i::FLAG_expose_gc = true; | 17103 i::FLAG_expose_gc = true; |
17017 v8::HandleScope scope; | 17104 v8::HandleScope scope; |
17018 LocalContext context; | 17105 LocalContext context; |
17019 | 17106 |
17020 // Compile a try-finally clause where the finally block causes a GC | 17107 // Compile a try-finally clause where the finally block causes a GC |
17021 // while there still is a message pending for external reporting. | 17108 // while there still is a message pending for external reporting. |
17022 TryCatch try_catch; | 17109 TryCatch try_catch; |
17023 try_catch.SetVerbose(true); | 17110 try_catch.SetVerbose(true); |
17024 CompileRun("try { throw new Error(); } finally { gc(); }"); | 17111 CompileRun("try { throw new Error(); } finally { gc(); }"); |
17025 CHECK(try_catch.HasCaught()); | 17112 CHECK(try_catch.HasCaught()); |
17026 } | 17113 } |
OLD | NEW |