From a0fcc6d4cf52cd8e803c12e6d0acffde2c3641fe Mon Sep 17 00:00:00 2001 From: Michael Colavita Date: Mon, 26 Oct 2020 18:19:20 -0700 Subject: [PATCH] Bespoke implementation of ClassGetTS Summary: Implement ClassGetTS for bespokes. Differential Revision: D24512398 fbshipit-source-id: f519cde6e972e5208cf16d7a83f10211f79cac47 --- hphp/doc/ir.specification | 2 +- hphp/runtime/base/type-structure-helpers-defs.h | 7 +++ hphp/runtime/vm/jit/irgen-basic.cpp | 9 ---- hphp/runtime/vm/jit/irgen-bespoke.cpp | 59 ++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/hphp/doc/ir.specification b/hphp/doc/ir.specification index b36a4a5a73b..75e51261b19 100644 --- a/hphp/doc/ir.specification +++ b/hphp/doc/ir.specification @@ -3115,7 +3115,7 @@ fields of that struct for holding intermediate values. Throws an OutOfBoundsException if S0 is an undefined index for an array. -| ThrowArrayKeyException, ND, S(DArr,Dict) S(Str), T +| ThrowArrayKeyException, ND, S(DArr,Dict) S(Str), T|LA Throws an OutOfBoundsException if S0 is an undefined key for a darray or dict. diff --git a/hphp/runtime/base/type-structure-helpers-defs.h b/hphp/runtime/base/type-structure-helpers-defs.h index c6a4949cad9..e0eb5c0c2ec 100644 --- a/hphp/runtime/base/type-structure-helpers-defs.h +++ b/hphp/runtime/base/type-structure-helpers-defs.h @@ -42,6 +42,13 @@ const StaticString s_root_name("root_name"); const StaticString s_alias("alias"); const StaticString s_hh_this("HH\\this"); +// Fixed error messages +const StaticString s_reified_type_must_be_ts( + "Reified type must be a type structure"); +const StaticString s_new_instance_of_not_string( + "You cannot create a new instance of this type as it is not a string"); + + /////////////////////////////////////////////////////////////////////////////// namespace detail { diff --git a/hphp/runtime/vm/jit/irgen-basic.cpp b/hphp/runtime/vm/jit/irgen-basic.cpp index 7c4a7f1dced..3c8d724ef17 100644 --- a/hphp/runtime/vm/jit/irgen-basic.cpp +++ b/hphp/runtime/vm/jit/irgen-basic.cpp @@ -31,15 +31,6 @@ namespace HPHP { namespace jit { namespace irgen { -namespace { - -const StaticString s_reified_type_must_be_ts( - "Reified type must be a type structure"); -const StaticString s_new_instance_of_not_string( - "You cannot create a new instance of this type as it is not a string"); - -} // namespace - void emitClassGetC(IRGS& env) { auto const name = topC(env); if (!name->type().subtypeOfAny(TObj, TCls, TStr, TLazyCls)) { diff --git a/hphp/runtime/vm/jit/irgen-bespoke.cpp b/hphp/runtime/vm/jit/irgen-bespoke.cpp index a77328e6b69..256ccb7b728 100644 --- a/hphp/runtime/vm/jit/irgen-bespoke.cpp +++ b/hphp/runtime/vm/jit/irgen-bespoke.cpp @@ -18,6 +18,7 @@ #include "hphp/runtime/base/bespoke-array.h" #include "hphp/runtime/base/bespoke/logging-array.h" #include "hphp/runtime/base/bespoke/logging-profile.h" +#include "hphp/runtime/base/type-structure-helpers-defs.h" #include "hphp/runtime/vm/jit/analysis.h" #include "hphp/runtime/vm/jit/irgen-builtin.h" @@ -458,6 +459,60 @@ void emitBespokeColFromArray(IRGS& env, CollectionType type) { push(env, col); } +void emitBespokeClassGetTS(IRGS& env) { + auto const reqType = RO::EvalHackArrDVArrs ? TDict : TDArr; + auto const arr = topC(env); + auto const arrType = arr->type(); + if (!(arrType <= reqType)) { + if (arrType.maybe(reqType)) { + PUNT(Bespoke-ClassGetTS-UnguardedTS); + } else { + gen(env, RaiseError, cns(env, s_reified_type_must_be_ts.get())); + return; + } + } + + auto const layout = arrType.arrSpec().bespokeLayout(); + ifElse( + env, + [&](Block* taken) { + layout->emitGet(env, arr, cns(env, s_generic_types.get()), taken); + }, + [&] { gen(env, Jmp, makeExitSlow(env)); } + ); + + auto const classKey = cns(env, s_classname.get()); + auto const classVal = cond( + env, + [&](Block* taken) { + return layout->emitGet(env, arr, classKey, taken); + }, + [&] (SSATmp* val) { return val; }, + [&] { + gen(env, ThrowArrayKeyException, arr, classKey); + return cns(env, TBottom); + } + ); + + auto const className = cond( + env, + [&] (Block* taken) { + return gen(env, CheckType, TStr, taken, classVal); + }, + [&] (SSATmp* val) { return val; }, + [&] { + hint(env, Block::Hint::Unlikely); + gen(env, RaiseError, cns(env, s_new_instance_of_not_string.get())); + return cns(env, TBottom); + } + ); + + auto const cls = ldCls(env, className); + popDecRef(env); + push(env, cls); + push(env, cns(env, TInitNull)); +} + void translateDispatchBespoke(IRGS& env, const NormalizedInstruction& ni) { auto const DEBUG_ONLY sk = ni.source; @@ -490,8 +545,10 @@ void translateDispatchBespoke(IRGS& env, case Op::ColFromArray: emitBespokeColFromArray(env, (CollectionType) ni.imm[0].u_OA); return; - case Op::FCallBuiltin: case Op::ClassGetTS: + emitBespokeClassGetTS(env); + return; + case Op::FCallBuiltin: interpOne(env); return; case Op::IterInit: -- 2.11.4.GIT