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

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: Avoid generating an interceptor when unused. 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 use(interceptor);
2247 2248
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); 2249 world.registerIsCheck(type, work.resolutionTree);
2261 2250
2262 js.PropertyAccess field = 2251 js.PropertyAccess field =
2263 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type)); 2252 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type));
2264 // We always negate at least once so that the result is boolified. 2253 // We always negate at least once so that the result is boolified.
2265 push(new js.Prefix('!', field)); 2254 push(new js.Prefix('!', field));
2266 // If the result is not negated, put another '!' in front. 2255 // If the result is not negated, put another '!' in front.
2267 if (!negative) push(new js.Prefix('!', pop())); 2256 if (!negative) push(new js.Prefix('!', pop()));
2268 } 2257 }
2269 2258
2270 void handleNumberOrStringSupertypeCheck(HInstruction input, 2259 void handleNumberOrStringSupertypeCheck(HInstruction input,
2260 HInstruction interceptor,
2271 DartType type, 2261 DartType type,
2272 { bool negative: false }) { 2262 { bool negative: false }) {
2273 assert(!identical(type.element, compiler.listClass) 2263 assert(!identical(type.element, compiler.listClass)
2274 && !Elements.isListSupertype(type.element, compiler) 2264 && !Elements.isListSupertype(type.element, compiler)
2275 && !Elements.isStringOnlySupertype(type.element, compiler)); 2265 && !Elements.isStringOnlySupertype(type.element, compiler));
2276 String relation = negative ? '!==' : '==='; 2266 String relation = negative ? '!==' : '===';
2277 checkNum(input, relation); 2267 checkNum(input, relation);
2278 js.Expression numberTest = pop(); 2268 js.Expression numberTest = pop();
2279 checkString(input, relation); 2269 checkString(input, relation);
2280 js.Expression stringTest = pop(); 2270 js.Expression stringTest = pop();
2281 checkObject(input, relation); 2271 checkObject(input, relation);
2282 js.Expression objectTest = pop(); 2272 js.Expression objectTest = pop();
2283 checkType(input, type, negative: negative); 2273 checkType(input, interceptor, type, negative: negative);
2284 String combiner = negative ? '&&' : '||'; 2274 String combiner = negative ? '&&' : '||';
2285 String combiner2 = negative ? '||' : '&&'; 2275 String combiner2 = negative ? '||' : '&&';
2286 push(new js.Binary(combiner, 2276 push(new js.Binary(combiner,
2287 new js.Binary(combiner, numberTest, stringTest), 2277 new js.Binary(combiner, numberTest, stringTest),
2288 new js.Binary(combiner2, objectTest, pop()))); 2278 new js.Binary(combiner2, objectTest, pop())));
2289 } 2279 }
2290 2280
2291 void handleStringSupertypeCheck(HInstruction input, 2281 void handleStringSupertypeCheck(HInstruction input,
2282 HInstruction interceptor,
2292 DartType type, 2283 DartType type,
2293 { bool negative: false }) { 2284 { bool negative: false }) {
2294 assert(!identical(type.element, compiler.listClass) 2285 assert(!identical(type.element, compiler.listClass)
2295 && !Elements.isListSupertype(type.element, compiler) 2286 && !Elements.isListSupertype(type.element, compiler)
2296 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2287 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2297 String relation = negative ? '!==' : '==='; 2288 String relation = negative ? '!==' : '===';
2298 checkString(input, relation); 2289 checkString(input, relation);
2299 js.Expression stringTest = pop(); 2290 js.Expression stringTest = pop();
2300 checkObject(input, relation); 2291 checkObject(input, relation);
2301 js.Expression objectTest = pop(); 2292 js.Expression objectTest = pop();
2302 checkType(input, type, negative: negative); 2293 checkType(input, interceptor, type, negative: negative);
2303 String combiner = negative ? '||' : '&&'; 2294 String combiner = negative ? '||' : '&&';
2304 push(new js.Binary(negative ? '&&' : '||', 2295 push(new js.Binary(negative ? '&&' : '||',
2305 stringTest, 2296 stringTest,
2306 new js.Binary(combiner, objectTest, pop()))); 2297 new js.Binary(combiner, objectTest, pop())));
2307 } 2298 }
2308 2299
2309 void handleListOrSupertypeCheck(HInstruction input, 2300 void handleListOrSupertypeCheck(HInstruction input,
2301 HInstruction interceptor,
2310 DartType type, 2302 DartType type,
2311 { bool negative: false }) { 2303 { bool negative: false }) {
2312 assert(!identical(type.element, compiler.stringClass) 2304 assert(!identical(type.element, compiler.stringClass)
2313 && !Elements.isStringOnlySupertype(type.element, compiler) 2305 && !Elements.isStringOnlySupertype(type.element, compiler)
2314 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2306 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2315 String relation = negative ? '!==' : '==='; 2307 String relation = negative ? '!==' : '===';
2316 checkObject(input, relation); 2308 checkObject(input, relation);
2317 js.Expression objectTest = pop(); 2309 js.Expression objectTest = pop();
2318 checkArray(input, relation); 2310 checkArray(input, relation);
2319 js.Expression arrayTest = pop(); 2311 js.Expression arrayTest = pop();
2320 checkType(input, type, negative: negative); 2312 checkType(input, interceptor, type, negative: negative);
2321 String combiner = negative ? '&&' : '||'; 2313 String combiner = negative ? '&&' : '||';
2322 push(new js.Binary(negative ? '||' : '&&', 2314 push(new js.Binary(negative ? '||' : '&&',
2323 objectTest, 2315 objectTest,
2324 new js.Binary(combiner, arrayTest, pop()))); 2316 new js.Binary(combiner, arrayTest, pop())));
2325 } 2317 }
2326 2318
2327 void visitIs(HIs node) { 2319 void visitIs(HIs node) {
2328 emitIs(node, "==="); 2320 emitIs(node, "===");
2329 } 2321 }
2330 2322
2331 void emitIs(HIs node, String relation) { 2323 void emitIs(HIs node, String relation) {
2332 DartType type = node.typeExpression; 2324 DartType type = node.typeExpression;
2333 world.registerIsCheck(type, work.resolutionTree); 2325 world.registerIsCheck(type, work.resolutionTree);
2334 HInstruction input = node.expression; 2326 HInstruction input = node.expression;
2335 2327
2336 // If this is changed to single == there are several places below that must 2328 // If this is changed to single == there are several places below that must
2337 // be changed to match. 2329 // be changed to match.
2338 assert(relation == '===' || relation == '!=='); 2330 assert(relation == '===' || relation == '!==');
2339 bool negative = relation == '!=='; 2331 bool negative = relation == '!==';
2340 2332
2341 if (node.isVariableCheck || node.isCompoundCheck) { 2333 if (node.isVariableCheck || node.isCompoundCheck) {
2342 use(node.checkCall); 2334 use(node.checkCall);
2343 if (negative) push(new js.Prefix('!', pop())); 2335 if (negative) push(new js.Prefix('!', pop()));
2344 } else { 2336 } else {
2345 assert(node.isRawCheck); 2337 assert(node.isRawCheck);
2338 HInstruction interceptor = node.interceptor;
2346 LibraryElement coreLibrary = compiler.coreLibrary; 2339 LibraryElement coreLibrary = compiler.coreLibrary;
2347 ClassElement objectClass = compiler.objectClass; 2340 ClassElement objectClass = compiler.objectClass;
2348 Element element = type.element; 2341 Element element = type.element;
2349 if (element == compiler.nullClass) { 2342 if (element == compiler.nullClass) {
2350 if (negative) { 2343 if (negative) {
2351 checkNonNull(input); 2344 checkNonNull(input);
2352 } else { 2345 } else {
2353 checkNull(input); 2346 checkNull(input);
2354 } 2347 }
2355 } else if (identical(element, objectClass) || type.treatAsDynamic) { 2348 } else if (identical(element, objectClass) || type.treatAsDynamic) {
(...skipping 14 matching lines...) Expand all
2370 attachLocationToLast(node); 2363 attachLocationToLast(node);
2371 } else if (element == compiler.intClass) { 2364 } else if (element == compiler.intClass) {
2372 // The is check in the code tells us that it might not be an 2365 // 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 2366 // int. So we do a typeof first to avoid possible
2374 // deoptimizations on the JS engine due to the Math.floor check. 2367 // deoptimizations on the JS engine due to the Math.floor check.
2375 checkNum(input, relation); 2368 checkNum(input, relation);
2376 js.Expression numTest = pop(); 2369 js.Expression numTest = pop();
2377 checkBigInt(input, relation); 2370 checkBigInt(input, relation);
2378 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node); 2371 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node);
2379 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { 2372 } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
2380 handleNumberOrStringSupertypeCheck(input, type, negative: negative); 2373 handleNumberOrStringSupertypeCheck(
2374 input, interceptor, type, negative: negative);
2381 attachLocationToLast(node); 2375 attachLocationToLast(node);
2382 } else if (Elements.isStringOnlySupertype(element, compiler)) { 2376 } else if (Elements.isStringOnlySupertype(element, compiler)) {
2383 handleStringSupertypeCheck(input, type, negative: negative); 2377 handleStringSupertypeCheck(
2378 input, interceptor, type, negative: negative);
2384 attachLocationToLast(node); 2379 attachLocationToLast(node);
2385 } else if (identical(element, compiler.listClass) 2380 } else if (identical(element, compiler.listClass)
2386 || Elements.isListSupertype(element, compiler)) { 2381 || Elements.isListSupertype(element, compiler)) {
2387 handleListOrSupertypeCheck(input, type, negative: negative); 2382 handleListOrSupertypeCheck(
2383 input, interceptor, type, negative: negative);
2388 attachLocationToLast(node); 2384 attachLocationToLast(node);
2389 } else if (element.isTypedef()) { 2385 } else if (type.kind == TypeKind.FUNCTION) {
2390 if (negative) { 2386 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); 2387 attachLocationToLast(node);
2399 } else if ((input.canBePrimitive(compiler) 2388 } else if ((input.canBePrimitive(compiler)
2400 && !input.canBePrimitiveArray(compiler)) 2389 && !input.canBePrimitiveArray(compiler))
2401 || input.canBeNull()) { 2390 || input.canBeNull()) {
2402 checkObject(input, relation); 2391 checkObject(input, relation);
2403 js.Expression objectTest = pop(); 2392 js.Expression objectTest = pop();
2404 checkType(input, type, negative: negative); 2393 checkType(input, interceptor, type, negative: negative);
2405 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node); 2394 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node);
2406 } else { 2395 } else {
2407 checkType(input, type, negative: negative); 2396 checkType(input, interceptor, type, negative: negative);
2408 attachLocationToLast(node); 2397 attachLocationToLast(node);
2409 } 2398 }
2410 } 2399 }
2411 if (node.nullOk) { 2400 if (node.nullOk) {
2412 if (negative) { 2401 if (negative) {
2413 checkNonNull(input); 2402 checkNonNull(input);
2414 push(new js.Binary('&&', pop(), pop()), node); 2403 push(new js.Binary('&&', pop(), pop()), node);
2415 } else { 2404 } else {
2416 checkNull(input); 2405 checkNull(input);
2417 push(new js.Binary('||', pop(), pop()), node); 2406 push(new js.Binary('||', pop(), pop()), node);
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2989 if (leftType.canBeNull() && rightType.canBeNull()) { 2978 if (leftType.canBeNull() && rightType.canBeNull()) {
2990 if (left.isConstantNull() || right.isConstantNull() || 2979 if (left.isConstantNull() || right.isConstantNull() ||
2991 (leftType.isPrimitive(compiler) && leftType == rightType)) { 2980 (leftType.isPrimitive(compiler) && leftType == rightType)) {
2992 return '=='; 2981 return '==';
2993 } 2982 }
2994 return null; 2983 return null;
2995 } else { 2984 } else {
2996 return '==='; 2985 return '===';
2997 } 2986 }
2998 } 2987 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698