From 83071cb1719a74d071f7aa3e580728048704e1ce Mon Sep 17 00:00:00 2001 From: Paul Leathers Date: Tue, 11 Sep 2018 16:35:28 -0700 Subject: [PATCH] Writing to proto can leave the TypeHandler::protoCachesWereInvalidated set, and writing to proto again with the same type on the RHS object can skip proto cache invalidation --- lib/Runtime/Library/JavascriptObject.cpp | 7 ++- test/InlineCaches/MissingProtoInval.js | 54 ++++++++++++++++++++++++ test/InlineCaches/rlexe.xml | 5 +++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 test/InlineCaches/MissingProtoInval.js diff --git a/lib/Runtime/Library/JavascriptObject.cpp b/lib/Runtime/Library/JavascriptObject.cpp index 4140201ee05..a204f4a6ed0 100644 --- a/lib/Runtime/Library/JavascriptObject.cpp +++ b/lib/Runtime/Library/JavascriptObject.cpp @@ -194,7 +194,7 @@ BOOL JavascriptObject::ChangePrototype(RecyclableObject* object, RecyclableObjec // ii. Let nextp be the result of calling the [[GetInheritance]] internal method of p with no arguments. // iii. ReturnIfAbrupt(nextp). // iv. Let p be nextp. - if (IsPrototypeOfStopAtProxy(object, newPrototype, scriptContext)) // Reject cycle + if (IsPrototypeOfStopAtProxy(object, newPrototype, scriptContext)) // Reject cycle { if (shouldThrow) { @@ -229,6 +229,11 @@ BOOL JavascriptObject::ChangePrototype(RecyclableObject* object, RecyclableObjec { bool allProtoCachesInvalidated = false; + JavascriptOperators::MapObjectAndPrototypes(newPrototype, [&](RecyclableObject* obj) + { + obj->ClearProtoCachesWereInvalidated(); + }); + // Notify old prototypes that they are being removed from a prototype chain. This triggers invalidating protocache, etc. JavascriptOperators::MapObjectAndPrototypesUntil(object->GetPrototype(), [&](RecyclableObject* obj)->bool { diff --git a/test/InlineCaches/MissingProtoInval.js b/test/InlineCaches/MissingProtoInval.js new file mode 100644 index 00000000000..f15873a92ca --- /dev/null +++ b/test/InlineCaches/MissingProtoInval.js @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +function f1() { + var o1 = {},o2 = {}; + var proto1 = {a:'a',b:'b'},proto2 = {a:'a'}; + o1.__proto__ = proto1; + o2.__proto__ = proto2; + + function a(o) { return o.a; } + function b(o) { return o.b; } + + a(o1); + a(o2); + b(o1); + b(o2); + proto2.__proto__ = {b:'b'}; + if (b(o2) !== 'b') { + WScript.Echo('fail'); + } +} + +f1() +f1(); + +function f2() { + var o1 = {b:'b'},o2 = {b:'b'}; + var proto1 = {a:'a',b:'b'},proto2 = {a:'a'}; + o1.__proto__ = proto1; + o2.__proto__ = proto2; + + function a(o) { return o.a; } + function b(o) { return o.b; } + + a(o1); + a(o2); + + delete o1.b; + delete o2.b; + + b(o1); + b(o2); + proto2.__proto__ = {b:'b'}; + if (b(o2) !== 'b') { + WScript.Echo('fail'); + } +} + +f2(); +f2(); + +WScript.Echo('pass'); diff --git a/test/InlineCaches/rlexe.xml b/test/InlineCaches/rlexe.xml index 163e0ef0155..9a684a2f88e 100644 --- a/test/InlineCaches/rlexe.xml +++ b/test/InlineCaches/rlexe.xml @@ -120,6 +120,11 @@ MissingPropertyCache4.js + + + MissingProtoInval.js + + instanceOfCacheCrossRegistration.js