Skip to content

Commit f7a300f

Browse files
rakudramacommit-bot@chromium.org
authored andcommitted
[dart2js] new-rti: signatures for tear-offs with dependent types
Change-Id: I0fd4e1b081500fe9a44897b1489cdd2b6680f409 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112440 Reviewed-by: Mayank Patke <[email protected]> Commit-Queue: Stephen Adams <[email protected]>
1 parent 4080ea7 commit f7a300f

File tree

3 files changed

+120
-43
lines changed

3 files changed

+120
-43
lines changed

pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import '../../js_backend/runtime_types.dart'
3131
import '../../js_backend/runtime_types_new.dart' show RecipeEncoder;
3232
import '../../js_backend/runtime_types_resolution.dart' show RuntimeTypesNeed;
3333
import '../../js_model/elements.dart' show JGeneratorBody, JSignatureMethod;
34+
import '../../js_model/type_recipe.dart'
35+
show FullTypeEnvironmentStructure, TypeExpressionRecipe;
3436
import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
3537
import '../../options.dart';
3638
import '../../universe/codegen_world_builder.dart';
@@ -926,7 +928,8 @@ class ProgramBuilder {
926928
js.Expression functionType;
927929
if (canTearOff) {
928930
OutputUnit outputUnit = _outputUnitData.outputUnitForMember(element);
929-
functionType = _generateFunctionType(memberType, outputUnit);
931+
functionType =
932+
_generateFunctionType(element.enclosingClass, memberType, outputUnit);
930933
}
931934

932935
FunctionEntity method = element;
@@ -955,12 +958,22 @@ class ProgramBuilder {
955958
applyIndex: applyIndex);
956959
}
957960

958-
js.Expression _generateFunctionType(
961+
js.Expression _generateFunctionType(ClassEntity /*?*/ enclosingClass,
959962
FunctionType type, OutputUnit outputUnit) {
960963
if (type.containsTypeVariables) {
961-
js.Expression thisAccess = js.js(r'this.$receiver');
962-
return _rtiEncoder.getSignatureEncoding(
963-
_namer, _task.emitter, type, thisAccess);
964+
if (_options.experimentNewRti) {
965+
// TODO(sra): The recipe might reference class type variables. Collect
966+
// these for the type metadata.
967+
return _rtiRecipeEncoder.encodeRecipe(
968+
_task.emitter,
969+
FullTypeEnvironmentStructure(
970+
classType: _elementEnvironment.getThisType(enclosingClass)),
971+
TypeExpressionRecipe(type));
972+
} else {
973+
js.Expression thisAccess = js.js(r'this.$receiver');
974+
return _rtiEncoder.getSignatureEncoding(
975+
_namer, _task.emitter, type, thisAccess);
976+
}
964977
} else {
965978
return _task.metadataCollector.reifyType(type, outputUnit);
966979
}
@@ -1180,7 +1193,7 @@ class ProgramBuilder {
11801193
DartType type = _elementEnvironment.getFunctionType(element);
11811194
if (needsTearOff) {
11821195
OutputUnit outputUnit = _outputUnitData.outputUnitForMember(element);
1183-
functionType = _generateFunctionType(type, outputUnit);
1196+
functionType = _generateFunctionType(null, type, outputUnit);
11841197
}
11851198

11861199
FunctionEntity method = element;

sdk/lib/_internal/js_runtime/lib/js_helper.dart

Lines changed: 96 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ import 'dart:_js_names'
6060
unmangleAllIdentifiersIfPreservedAnyways;
6161

6262
import 'dart:_rti' as newRti
63-
show createRuntimeType, getRuntimeType, getTypeFromTypesTable;
63+
show
64+
createRuntimeType,
65+
evalInInstance,
66+
getRuntimeType,
67+
getTypeFromTypesTable;
6468

6569
part 'annotations.dart';
6670
part 'constant_map.dart';
@@ -2039,8 +2043,12 @@ abstract class Closure implements Function {
20392043
// The functions are called here to model the calls from JS forms below.
20402044
// The types in the JS forms in the arguments are propagated in type
20412045
// inference.
2042-
BoundClosure.receiverOf(JS('BoundClosure', '0'));
2043-
BoundClosure.selfOf(JS('BoundClosure', '0'));
2046+
var aBoundClosure = JS('BoundClosure', '0');
2047+
var aString = JS('String', '0');
2048+
BoundClosure.receiverOf(aBoundClosure);
2049+
BoundClosure.selfOf(aBoundClosure);
2050+
BoundClosure.evalRecipeIntercepted(aBoundClosure, aString);
2051+
BoundClosure.evalRecipe(aBoundClosure, aString);
20442052
getType(JS('int', '0'));
20452053
});
20462054
// TODO(ahe): All the place below using \$ should be rewritten to go
@@ -2119,7 +2127,41 @@ abstract class Closure implements Function {
21192127
propertyName);
21202128
}
21212129

2122-
var signatureFunction;
2130+
var signatureFunction = JS_GET_FLAG('USE_NEW_RTI')
2131+
? _computeSignatureFunctionNewRti(functionType, isStatic, isIntercepted)
2132+
: _computeSignatureFunctionLegacy(
2133+
functionType, isStatic, isIntercepted);
2134+
2135+
JS('', '#[#] = #', prototype, JS_GET_NAME(JsGetName.SIGNATURE_NAME),
2136+
signatureFunction);
2137+
var applyTrampoline = trampoline;
2138+
JS('', '#[#] = #', prototype, callName, trampoline);
2139+
for (int i = 1; i < functions.length; i++) {
2140+
var stub = functions[i];
2141+
var stubCallName = JS('String|Null', '#[#]', stub,
2142+
JS_GET_NAME(JsGetName.CALL_NAME_PROPERTY));
2143+
if (stubCallName != null) {
2144+
stub = isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted);
2145+
JS('', '#[#] = #', prototype, stubCallName, stub);
2146+
}
2147+
if (i == applyTrampolineIndex) {
2148+
applyTrampoline = stub;
2149+
JS('', '#.\$reflectionInfo = #', applyTrampoline, reflectionInfo);
2150+
}
2151+
}
2152+
2153+
JS('', '#[#] = #', prototype, JS_GET_NAME(JsGetName.CALL_CATCH_ALL),
2154+
applyTrampoline);
2155+
String reqArgProperty = JS_GET_NAME(JsGetName.REQUIRED_PARAMETER_PROPERTY);
2156+
String defValProperty = JS_GET_NAME(JsGetName.DEFAULT_VALUES_PROPERTY);
2157+
JS('', '#.# = #.#', prototype, reqArgProperty, function, reqArgProperty);
2158+
JS('', '#.# = #.#', prototype, defValProperty, function, defValProperty);
2159+
2160+
return constructor;
2161+
}
2162+
2163+
static _computeSignatureFunctionLegacy(
2164+
Object functionType, bool isStatic, bool isIntercepted) {
21232165
if (JS('bool', 'typeof # == "number"', functionType)) {
21242166
// We cannot call [getType] here, since the types-metadata might not be
21252167
// set yet. This is, because fromTearOff might be called for constants
@@ -2128,23 +2170,22 @@ abstract class Closure implements Function {
21282170
// Note that we cannot just textually inline the call
21292171
// `getType(functionType)` since we cannot guarantee that the (then)
21302172
// captured variable `functionType` isn't reused.
2131-
signatureFunction = JS(
2173+
return JS(
21322174
'',
21332175
'''(function(getType, t) {
21342176
return function(){ return getType(t); };
21352177
})(#, #)''',
2136-
JS_GET_FLAG('USE_NEW_RTI')
2137-
? RAW_DART_FUNCTION_REF(newRti.getTypeFromTypesTable)
2138-
: RAW_DART_FUNCTION_REF(getType),
2178+
RAW_DART_FUNCTION_REF(getType),
21392179
functionType);
2140-
} else if (JS('bool', 'typeof # == "function"', functionType)) {
2180+
}
2181+
if (JS('bool', 'typeof # == "function"', functionType)) {
21412182
if (isStatic) {
2142-
signatureFunction = functionType;
2183+
return functionType;
21432184
} else {
21442185
var getReceiver = isIntercepted
21452186
? RAW_DART_FUNCTION_REF(BoundClosure.receiverOf)
21462187
: RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
2147-
signatureFunction = JS(
2188+
return JS(
21482189
'',
21492190
'function(f,r){'
21502191
'return function(){'
@@ -2154,36 +2195,46 @@ abstract class Closure implements Function {
21542195
functionType,
21552196
getReceiver);
21562197
}
2157-
} else {
2158-
throw 'Error in reflectionInfo.';
21592198
}
2199+
throw 'Error in functionType of tearoff';
2200+
}
21602201

2161-
JS('', '#[#] = #', prototype, JS_GET_NAME(JsGetName.SIGNATURE_NAME),
2162-
signatureFunction);
2163-
var applyTrampoline = trampoline;
2164-
JS('', '#[#] = #', prototype, callName, trampoline);
2165-
for (int i = 1; i < functions.length; i++) {
2166-
var stub = functions[i];
2167-
var stubCallName = JS('String|Null', '#[#]', stub,
2168-
JS_GET_NAME(JsGetName.CALL_NAME_PROPERTY));
2169-
if (stubCallName != null) {
2170-
stub = isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted);
2171-
JS('', '#[#] = #', prototype, stubCallName, stub);
2172-
}
2173-
if (i == applyTrampolineIndex) {
2174-
applyTrampoline = stub;
2175-
JS('', '#.\$reflectionInfo = #', applyTrampoline, reflectionInfo);
2202+
static _computeSignatureFunctionNewRti(
2203+
Object functionType, bool isStatic, bool isIntercepted) {
2204+
if (JS('bool', 'typeof # == "number"', functionType)) {
2205+
// Index into types table.
2206+
//
2207+
// We cannot call [getTypeFromTypesTable] here, since the types-metadata
2208+
// might not be set yet. This is, because fromTearOff might be called for
2209+
// constants when the program isn't completely set up yet. We also want to
2210+
// avoid creating lots of types at startup.
2211+
return JS(
2212+
'',
2213+
'''(function(getType, t) {
2214+
return function(){ return getType(t); };
2215+
})(#, #)''',
2216+
RAW_DART_FUNCTION_REF(newRti.getTypeFromTypesTable),
2217+
functionType);
2218+
}
2219+
if (JS('bool', 'typeof # == "string"', functionType)) {
2220+
// A recipe to evaluate against the instance type.
2221+
if (isStatic) {
2222+
throw 'TODO: Recipe for static tearoff.';
21762223
}
2224+
var typeEvalMethod = isIntercepted
2225+
? RAW_DART_FUNCTION_REF(BoundClosure.evalRecipeIntercepted)
2226+
: RAW_DART_FUNCTION_REF(BoundClosure.evalRecipe);
2227+
return JS(
2228+
'',
2229+
' function(recipe, evalOnReceiver) {'
2230+
' return function() {'
2231+
' return evalOnReceiver(this, recipe);'
2232+
' };'
2233+
'}(#,#)',
2234+
functionType,
2235+
typeEvalMethod);
21772236
}
2178-
2179-
JS('', '#[#] = #', prototype, JS_GET_NAME(JsGetName.CALL_CATCH_ALL),
2180-
applyTrampoline);
2181-
String reqArgProperty = JS_GET_NAME(JsGetName.REQUIRED_PARAMETER_PROPERTY);
2182-
String defValProperty = JS_GET_NAME(JsGetName.DEFAULT_VALUES_PROPERTY);
2183-
JS('', '#.# = #.#', prototype, reqArgProperty, function, reqArgProperty);
2184-
JS('', '#.# = #.#', prototype, defValProperty, function, defValProperty);
2185-
2186-
return constructor;
2237+
throw 'Error in functionType of tearoff';
21872238
}
21882239

21892240
static cspForwardCall(
@@ -2531,6 +2582,14 @@ class BoundClosure extends TearOffClosure {
25312582
"${Primitives.objectToHumanReadableString(receiver)}";
25322583
}
25332584

2585+
static evalRecipe(BoundClosure closure, String recipe) {
2586+
return newRti.evalInInstance(closure._self, recipe);
2587+
}
2588+
2589+
static evalRecipeIntercepted(BoundClosure closure, String recipe) {
2590+
return newRti.evalInInstance(closure._receiver, recipe);
2591+
}
2592+
25342593
@pragma('dart2js:noInline')
25352594
static selfOf(BoundClosure closure) => closure._self;
25362595

sdk/lib/_internal/js_runtime/lib/rti.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,11 @@ Rti findType(String recipe) {
341341
return _Universe.eval(_theUniverse(), recipe);
342342
}
343343

344+
/// Evaluate a type recipe in the environment of an instance.
345+
Rti evalInInstance(instance, String recipe) {
346+
return _rtiEval(instanceType(instance), recipe);
347+
}
348+
344349
/// Returns the Rti type of [object]. Closures have both an interface type
345350
/// (Closures implement `Function`) and a structural function type. Uses
346351
/// [testRti] to choose the appropriate type.

0 commit comments

Comments
 (0)