Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(442)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart

Issue 23003031: Extract interceptor calls from raw is-checks. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 class SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 10
(...skipping 2198 matching lines...) Expand 10 before | Expand all | Expand 10 after
2209 2209
2210 List<js.Expression> arguments = <js.Expression>[object, record]; 2210 List<js.Expression> arguments = <js.Expression>[object, record];
2211 FunctionElement helper = 2211 FunctionElement helper =
2212 compiler.findHelper(const SourceString('isJsIndexable')); 2212 compiler.findHelper(const SourceString('isJsIndexable'));
2213 world.registerStaticUse(helper); 2213 world.registerStaticUse(helper);
2214 String helperName = backend.namer.isolateAccess(helper); 2214 String helperName = backend.namer.isolateAccess(helper);
2215 push(new js.Call(new js.VariableUse(helperName), arguments)); 2215 push(new js.Call(new js.VariableUse(helperName), arguments));
2216 if (negative) push(new js.Prefix('!', pop())); 2216 if (negative) push(new js.Prefix('!', pop()));
2217 } 2217 }
2218 2218
2219 void checkType(HInstruction input, DartType type, {bool negative: false}) { 2219 void checkType(HInstruction input, HInstruction interceptor,
2220 DartType type, {bool negative: false}) {
2220 Element element = type.element; 2221 Element element = type.element;
2221 if (element == backend.jsArrayClass) { 2222 if (element == backend.jsArrayClass) {
2222 checkArray(input, negative ? '!==': '==='); 2223 checkArray(input, negative ? '!==': '===');
2223 return; 2224 return;
2224 } else if (element == backend.jsMutableArrayClass) { 2225 } else if (element == backend.jsMutableArrayClass) {
2225 if (negative) { 2226 if (negative) {
2226 checkImmutableArray(input); 2227 checkImmutableArray(input);
2227 } else { 2228 } else {
2228 checkMutableArray(input); 2229 checkMutableArray(input);
2229 } 2230 }
2230 return; 2231 return;
2231 } else if (element == backend.jsExtendableArrayClass) { 2232 } else if (element == backend.jsExtendableArrayClass) {
2232 if (negative) { 2233 if (negative) {
2233 checkFixedArray(input); 2234 checkFixedArray(input);
2234 } else { 2235 } else {
2235 checkExtendableArray(input); 2236 checkExtendableArray(input);
2236 } 2237 }
2237 return; 2238 return;
2238 } else if (element == backend.jsFixedArrayClass) { 2239 } else if (element == backend.jsFixedArrayClass) {
2239 if (negative) { 2240 if (negative) {
2240 checkExtendableArray(input); 2241 checkExtendableArray(input);
2241 } else { 2242 } else {
2242 checkFixedArray(input); 2243 checkFixedArray(input);
2243 } 2244 }
2244 return; 2245 return;
2245 } 2246 }
2246 use(input); 2247 if (interceptor != null) {
2248 use(interceptor);
2249 } else {
2250 use(input);
2251 }
2247 2252
2248 // Hack in interceptor. Ideally the interceptor would occur at the
2249 // instruction level to allow optimizations, and checks would be broken into
2250 // several smaller tests.
2251 // This code is a slice of visitInterceptor for the univeral interceptor.
2252 String interceptorName = backend.namer.getInterceptorName(
2253 backend.getInterceptorMethod, backend.interceptedClasses);
2254 backend.registerSpecializedGetInterceptor(backend.interceptedClasses);
2255 backend.registerUseInterceptor(world);
2256
2257 var isolate = new js.VariableUse(backend.namer.CURRENT_ISOLATE);
2258 List<js.Expression> arguments = <js.Expression>[pop()];
2259 push(jsPropertyCall(isolate, interceptorName, arguments));
2260 world.registerIsCheck(type, work.resolutionTree); 2253 world.registerIsCheck(type, work.resolutionTree);
2261 2254
2262 js.PropertyAccess field = 2255 js.PropertyAccess field =
2263 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type)); 2256 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type));
2264 // We always negate at least once so that the result is boolified. 2257 // We always negate at least once so that the result is boolified.
2265 push(new js.Prefix('!', field)); 2258 push(new js.Prefix('!', field));
2266 // If the result is not negated, put another '!' in front. 2259 // If the result is not negated, put another '!' in front.
2267 if (!negative) push(new js.Prefix('!', pop())); 2260 if (!negative) push(new js.Prefix('!', pop()));
2268 } 2261 }
2269 2262
2270 void handleNumberOrStringSupertypeCheck(HInstruction input, 2263 void handleNumberOrStringSupertypeCheck(HInstruction input,
2264 HInstruction interceptor,
2271 DartType type, 2265 DartType type,
2272 { bool negative: false }) { 2266 { bool negative: false }) {
2273 assert(!identical(type.element, compiler.listClass) 2267 assert(!identical(type.element, compiler.listClass)
2274 && !Elements.isListSupertype(type.element, compiler) 2268 && !Elements.isListSupertype(type.element, compiler)
2275 && !Elements.isStringOnlySupertype(type.element, compiler)); 2269 && !Elements.isStringOnlySupertype(type.element, compiler));
2276 String relation = negative ? '!==' : '==='; 2270 String relation = negative ? '!==' : '===';
2277 checkNum(input, relation); 2271 checkNum(input, relation);
2278 js.Expression numberTest = pop(); 2272 js.Expression numberTest = pop();
2279 checkString(input, relation); 2273 checkString(input, relation);
2280 js.Expression stringTest = pop(); 2274 js.Expression stringTest = pop();
2281 checkObject(input, relation); 2275 checkObject(input, relation);
2282 js.Expression objectTest = pop(); 2276 js.Expression objectTest = pop();
2283 checkType(input, type, negative: negative); 2277 checkType(input, interceptor, type, negative: negative);
2284 String combiner = negative ? '&&' : '||'; 2278 String combiner = negative ? '&&' : '||';
2285 String combiner2 = negative ? '||' : '&&'; 2279 String combiner2 = negative ? '||' : '&&';
2286 push(new js.Binary(combiner, 2280 push(new js.Binary(combiner,
2287 new js.Binary(combiner, numberTest, stringTest), 2281 new js.Binary(combiner, numberTest, stringTest),
2288 new js.Binary(combiner2, objectTest, pop()))); 2282 new js.Binary(combiner2, objectTest, pop())));
2289 } 2283 }
2290 2284
2291 void handleStringSupertypeCheck(HInstruction input, 2285 void handleStringSupertypeCheck(HInstruction input,
2286 HInstruction interceptor,
2292 DartType type, 2287 DartType type,
2293 { bool negative: false }) { 2288 { bool negative: false }) {
2294 assert(!identical(type.element, compiler.listClass) 2289 assert(!identical(type.element, compiler.listClass)
2295 && !Elements.isListSupertype(type.element, compiler) 2290 && !Elements.isListSupertype(type.element, compiler)
2296 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2291 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2297 String relation = negative ? '!==' : '==='; 2292 String relation = negative ? '!==' : '===';
2298 checkString(input, relation); 2293 checkString(input, relation);
2299 js.Expression stringTest = pop(); 2294 js.Expression stringTest = pop();
2300 checkObject(input, relation); 2295 checkObject(input, relation);
2301 js.Expression objectTest = pop(); 2296 js.Expression objectTest = pop();
2302 checkType(input, type, negative: negative); 2297 checkType(input, interceptor, type, negative: negative);
2303 String combiner = negative ? '||' : '&&'; 2298 String combiner = negative ? '||' : '&&';
2304 push(new js.Binary(negative ? '&&' : '||', 2299 push(new js.Binary(negative ? '&&' : '||',
2305 stringTest, 2300 stringTest,
2306 new js.Binary(combiner, objectTest, pop()))); 2301 new js.Binary(combiner, objectTest, pop())));
2307 } 2302 }
2308 2303
2309 void handleListOrSupertypeCheck(HInstruction input, 2304 void handleListOrSupertypeCheck(HInstruction input,
2305 HInstruction interceptor,
2310 DartType type, 2306 DartType type,
2311 { bool negative: false }) { 2307 { bool negative: false }) {
2312 assert(!identical(type.element, compiler.stringClass) 2308 assert(!identical(type.element, compiler.stringClass)
2313 && !Elements.isStringOnlySupertype(type.element, compiler) 2309 && !Elements.isStringOnlySupertype(type.element, compiler)
2314 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2310 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2315 String relation = negative ? '!==' : '==='; 2311 String relation = negative ? '!==' : '===';
2316 checkObject(input, relation); 2312 checkObject(input, relation);
2317 js.Expression objectTest = pop(); 2313 js.Expression objectTest = pop();
2318 checkArray(input, relation); 2314 checkArray(input, relation);
2319 js.Expression arrayTest = pop(); 2315 js.Expression arrayTest = pop();
2320 checkType(input, type, negative: negative); 2316 checkType(input, interceptor, type, negative: negative);
2321 String combiner = negative ? '&&' : '||'; 2317 String combiner = negative ? '&&' : '||';
2322 push(new js.Binary(negative ? '||' : '&&', 2318 push(new js.Binary(negative ? '||' : '&&',
2323 objectTest, 2319 objectTest,
2324 new js.Binary(combiner, arrayTest, pop()))); 2320 new js.Binary(combiner, arrayTest, pop())));
2325 } 2321 }
2326 2322
2327 void visitIs(HIs node) { 2323 void visitIs(HIs node) {
2328 emitIs(node, "==="); 2324 emitIs(node, "===");
2329 } 2325 }
2330 2326
2331 void emitIs(HIs node, String relation) { 2327 void emitIs(HIs node, String relation) {
2332 DartType type = node.typeExpression; 2328 DartType type = node.typeExpression;
2333 world.registerIsCheck(type, work.resolutionTree); 2329 world.registerIsCheck(type, work.resolutionTree);
2334 HInstruction input = node.expression; 2330 HInstruction input = node.expression;
2335 2331
2336 // If this is changed to single == there are several places below that must 2332 // If this is changed to single == there are several places below that must
2337 // be changed to match. 2333 // be changed to match.
2338 assert(relation == '===' || relation == '!=='); 2334 assert(relation == '===' || relation == '!==');
2339 bool negative = relation == '!=='; 2335 bool negative = relation == '!==';
2340 2336
2341 if (node.isVariableCheck || node.isCompoundCheck) { 2337 if (node.isVariableCheck || node.isCompoundCheck) {
2342 use(node.checkCall); 2338 use(node.checkCall);
2343 if (negative) push(new js.Prefix('!', pop())); 2339 if (negative) push(new js.Prefix('!', pop()));
2344 } else { 2340 } else {
2345 assert(node.isRawCheck); 2341 assert(node.isRawCheck);
2342 HInstruction interceptor = node.interceptor;
2346 LibraryElement coreLibrary = compiler.coreLibrary; 2343 LibraryElement coreLibrary = compiler.coreLibrary;
2347 ClassElement objectClass = compiler.objectClass; 2344 ClassElement objectClass = compiler.objectClass;
2348 Element element = type.element; 2345 Element element = type.element;
2349 if (element == compiler.nullClass) { 2346 if (element == compiler.nullClass) {
2350 if (negative) { 2347 if (negative) {
2351 checkNonNull(input); 2348 checkNonNull(input);
2352 } else { 2349 } else {
2353 checkNull(input); 2350 checkNull(input);
2354 } 2351 }
2355 } else if (identical(element, objectClass) || type.treatAsDynamic) { 2352 } else if (identical(element, objectClass) || type.treatAsDynamic) {
(...skipping 14 matching lines...) Expand all
2370 attachLocationToLast(node); 2367 attachLocationToLast(node);
2371 } else if (element == compiler.intClass) { 2368 } else if (element == compiler.intClass) {
2372 // The is check in the code tells us that it might not be an 2369 // The is check in the code tells us that it might not be an
2373 // int. So we do a typeof first to avoid possible 2370 // int. So we do a typeof first to avoid possible
2374 // deoptimizations on the JS engine due to the Math.floor check. 2371 // deoptimizations on the JS engine due to the Math.floor check.
2375 checkNum(input, relation); 2372 checkNum(input, relation);
2376 js.Expression numTest = pop(); 2373 js.Expression numTest = pop();
2377 checkBigInt(input, relation); 2374 checkBigInt(input, relation);
2378 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node); 2375 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node);
2379 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { 2376 } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
2380 handleNumberOrStringSupertypeCheck(input, type, negative: negative); 2377 handleNumberOrStringSupertypeCheck(
2378 input, interceptor, type, negative: negative);
2381 attachLocationToLast(node); 2379 attachLocationToLast(node);
2382 } else if (Elements.isStringOnlySupertype(element, compiler)) { 2380 } else if (Elements.isStringOnlySupertype(element, compiler)) {
2383 handleStringSupertypeCheck(input, type, negative: negative); 2381 handleStringSupertypeCheck(
2382 input, interceptor, type, negative: negative);
2384 attachLocationToLast(node); 2383 attachLocationToLast(node);
2385 } else if (identical(element, compiler.listClass) 2384 } else if (identical(element, compiler.listClass)
2386 || Elements.isListSupertype(element, compiler)) { 2385 || Elements.isListSupertype(element, compiler)) {
2387 handleListOrSupertypeCheck(input, type, negative: negative); 2386 handleListOrSupertypeCheck(
2387 input, interceptor, type, negative: negative);
2388 attachLocationToLast(node); 2388 attachLocationToLast(node);
2389 } else if (element.isTypedef()) { 2389 } else if (type.kind == TypeKind.FUNCTION) {
2390 if (negative) { 2390 checkType(input, interceptor, type, negative: negative);
2391 checkNull(input);
2392 } else {
2393 checkNonNull(input);
2394 }
2395 js.Expression nullTest = pop();
2396 checkType(input, type, negative: negative);
2397 push(new js.Binary(negative ? '||' : '&&', nullTest, pop()));
2398 attachLocationToLast(node); 2391 attachLocationToLast(node);
2399 } else if ((input.canBePrimitive(compiler) 2392 } else if ((input.canBePrimitive(compiler)
2400 && !input.canBePrimitiveArray(compiler)) 2393 && !input.canBePrimitiveArray(compiler))
2401 || input.canBeNull()) { 2394 || input.canBeNull()) {
2402 checkObject(input, relation); 2395 checkObject(input, relation);
2403 js.Expression objectTest = pop(); 2396 js.Expression objectTest = pop();
2404 checkType(input, type, negative: negative); 2397 checkType(input, interceptor, type, negative: negative);
2405 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node); 2398 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node);
2406 } else { 2399 } else {
2407 checkType(input, type, negative: negative); 2400 checkType(input, interceptor, type, negative: negative);
2408 attachLocationToLast(node); 2401 attachLocationToLast(node);
2409 } 2402 }
2410 } 2403 }
2411 if (node.nullOk) {
2412 if (negative) {
2413 checkNonNull(input);
2414 push(new js.Binary('&&', pop(), pop()), node);
2415 } else {
2416 checkNull(input);
2417 push(new js.Binary('||', pop(), pop()), node);
2418 }
2419 }
2420 } 2404 }
2421 2405
2422 js.Expression generateTest(HCheck node) { 2406 js.Expression generateTest(HCheck node) {
2423 HInstruction input = node.checkedInput; 2407 HInstruction input = node.checkedInput;
2424 TypeMask receiver = input.instructionType.computeMask(compiler); 2408 TypeMask receiver = input.instructionType.computeMask(compiler);
2425 TypeMask mask = node.instructionType.computeMask(compiler); 2409 TypeMask mask = node.instructionType.computeMask(compiler);
2426 bool turnIntoNullCheck = mask.nullable() == receiver; 2410 bool turnIntoNullCheck = mask.nullable() == receiver;
2427 js.Expression test; 2411 js.Expression test;
2428 if (turnIntoNullCheck) { 2412 if (turnIntoNullCheck) {
2429 use(input); 2413 use(input);
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after
2989 if (leftType.canBeNull() && rightType.canBeNull()) { 2973 if (leftType.canBeNull() && rightType.canBeNull()) {
2990 if (left.isConstantNull() || right.isConstantNull() || 2974 if (left.isConstantNull() || right.isConstantNull() ||
2991 (leftType.isPrimitive(compiler) && leftType == rightType)) { 2975 (leftType.isPrimitive(compiler) && leftType == rightType)) {
2992 return '=='; 2976 return '==';
2993 } 2977 }
2994 return null; 2978 return null;
2995 } else { 2979 } else {
2996 return '==='; 2980 return '===';
2997 } 2981 }
2998 } 2982 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698