Repository navigation
runtime/codegen: one exact int32 predicate; top-16-only tests misread 0x7FFE markers as Numbers - #14353
Merged
Conversation
…x7FFE word (C.prototype ref) is never read as an int32
…48 / 32766 (cherry picked from commit a58890bc017572de7d5c7046e3d430c5f852f2aa)
…feedback/tests.rs (+15 exact-int32 test)
|
Caution Review failedThe pull request is closed.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Correctness: one exact "is this an int32 Number?" predicate everywhere. About 40 runtime, codegen and perry-ffi sites tested only the top 16 bits (
bits & TAG_MASK == INT32_TAG,>> 48 == 0x7FFE,& 0xFFFF_0000_0000_0000). So they read any other0x7FFEword with bits 32..47 set as an int32 Number whose value is the low 32 bits. The JS-visible case is theC.prototypereference word (CLASS_PROTOTYPE_REF_FLAG, bit 32): as an index it read elementclass_id, it compared equal to the Numberclass_id, and with class id 0 it was falsy. It is latent: the P3 review tried about 30 shapes and could not reach that word from JS. The proof is the unit tests below, which fail on main.The one predicate
value::is_int32_bits(bits),bits & !INT32_MASK == INT32_TAG(value/tags.rs).JSValue::is_int32calls it.codegen::emit_int32_bits_test(blk, bits)(codegen/typed_entry.rs).emit_int32_box_testcalls it, and the duplicated exact sequences intyped_abi(4) andswitch_stmtnow call it.JSValue::is_int32uses the same mask.Sites
(A) Number consumers → the predicate (32). A non-Number
0x7FFEword is now an object at each one: truthy, not an index,NaNas a number.thread.rs:179,value/truthy.rs:73;value/dyn_index.rs:109,122,object/polymorphic_index.rs:99,112,array/indexing_keyed.rs:178,281,452,array/indexing_read_cold.rs:190,object/field_get_set/runtime_read_site.rs:238,typed_feedback.rs:1207,1220;object/buffer_dispatch.rs:1151,1189,buffer/cmp.rs:235,304,byte_cell_support/mod.rs:511,typedarray/construct.rs:53;json/stringify_scalars.rs:33,json/stringify_flat.rs:175;date.rs:549(nowNaN, never the tagged word);array/generic.rs:104(ToObject);object/object_ops/define_property.rs:327;gc/barrier_store.rs:89(raw-slot canonicalization);pty/mod.rs:288,object/native_module_dispatch.rs:143;node_submodules/diagnostics_tail.rs:77;closure/dispatch/value_call.rs:410.jsvalue.rs:266.expr/index_key.rs:119(the dynamic index-key normalizer);expr/compare.rs:771,774,832,887,955(strict equality, relational and normalization against a Number);expr/compare_chain.rs:227;lower_call/property_get/builtin_kind_guard.rs:569.(C) Kind classifiers → the predicate (5). A non-Number
0x7FFEword is no longer the Number/int32 kind:wpfacts_check.rs:63(check-modekind_of:K_OBJ);contracts.rs:361(contractkind_of:K_OBJ);typed_feedback.rs:494(stable_value_kind);gc/census.rs:284andgc/census_field_repr.rs:44.(B) Left alone: marker decoders and producers, which read their own marker correctly.
object/native_module/class_ref_values.rs:22,27,34,51,object/class_value.rs:126,400,412.closure/dispatch/bound.rs:359,442,448.closure/dispatch/value_call.rs:113,proxy.rs:151,object/property_ops/callable.rs:12,object/polymorphic_index.rs:179,object/field_get_set/ic_miss/private_member_access.rs:142,object/field_get_set/get_slow.rs:159,object/field_get_set/get_field_by_name.rs:107,object/native_call_method/primitive_methods.rs:202,object/native_call_method/common_methods.rs:412,469.proxy/metadata/storage.rs:21,object/property_ops/metadata/storage.rs:25.object/overflow.rs,object/key_attrs.rs:225,box/scope.rs:26.Other sites, unchanged:
thread/clone_write.rs:460(Inline(bits)).map.rs:675.snap_census/runner.rs:3329,gc/fromspace_scan.rs:438,typed_feedback/trace.rs:54.object/field_get_set/field_ops.rs:110,json/replacer.rs:1340.node_v8.rs:592(as_u32).What no bit test can separate
The bound-closure inline-args marker, the overflow route words, the class-id capture and the legacy constructor-ref key (
INT32_TAG | class_id) keep their payload in the low 32 bits. They are bit-identical to an int32 Number. They stay internal, and moving them to their own tag is RFC §10 P3 phase B2.Tests
They fail on main: branch
probe/int32-tests-on-mainis main plus only these tests.C.prototyperef word, and a0x7FFEword with high payload bits, and expects "not int32":value/int32_exact_tests.rs(the predicate,JSValue::is_int32,js_is_truthy,integer_key);typed_feedback/tests.rs,date/tests.rs,value/dyn_index_uint8array_tests.rs;object/polymorphic_index_int32_exact_tests.rs,thread_int32_exact_tests.rs;contracts.rs,wpfacts_check.rs,gc/census.rsandgc/census_field_repr.rs.dynamic_strict_eq_against_number_compares_both_encodings_without_js_eqasserts the emitted test uses the identity mask and nevericmp eq … 32766.Gates
Gates were run on the merged head (main dda8f1e merged in, no rebase), on qb9 (x86-64 Linux); the tests-on-main runs were on the Mac.
check -D warnings(codegen, ffi, perry) clean; codegen lib 2837/0; perry-runtime 6601/0; perry-ffi 55/0 and 5/0; file size OKJSValue::is_int32was already exact);contracts(under--cfg perry_contract_checks) 1 fails; the codegen IR test fails-D warnings-p perry-runtimealone reports 4 dead-code/unused errors in files this PR does not touch (webassembly_wrapper_state.rs,cell_meta.rs,gc/mark.rs,shapes.rs). They are pre-existing on main: main reports the same 4contractsunder--cfg perry_contract_checks6/0.text1238, identical; hello2.text5926142 → 5926014 (−128 B)typed_feedback.rsre-asserted 2436 → 2437,typed_feedback/tests.rs2289 → 2304.snap_census/runner.rs(3572) is over the cap on main itself and is handled separatelyChangelog:
runtime-exact-int32-predicate.md.