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

Side by Side Diff: src/type-info.cc

Issue 10837165: Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps … (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback; fixed tests Created 8 years, 1 month 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
« no previous file with comments | « src/type-info.h ('k') | src/x64/code-stubs-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId())); 305 return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId()));
306 } 306 }
307 307
308 308
309 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { 309 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
310 return *GetInfo(expr->PropertyFeedbackId()) == 310 return *GetInfo(expr->PropertyFeedbackId()) ==
311 isolate_->builtins()->builtin(id); 311 isolate_->builtins()->builtin(id);
312 } 312 }
313 313
314 314
315 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { 315 static TypeInfo TypeFromCompareType(CompareIC::State state) {
316 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
317 TypeInfo unknown = TypeInfo::Unknown();
318 if (!object->IsCode()) return unknown;
319 Handle<Code> code = Handle<Code>::cast(object);
320 if (!code->is_compare_ic_stub()) return unknown;
321
322 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
323 switch (state) { 316 switch (state) {
324 case CompareIC::UNINITIALIZED: 317 case CompareIC::UNINITIALIZED:
325 // Uninitialized means never executed. 318 // Uninitialized means never executed.
326 return TypeInfo::Uninitialized(); 319 return TypeInfo::Uninitialized();
327 case CompareIC::SMIS: 320 case CompareIC::SMI:
328 return TypeInfo::Smi(); 321 return TypeInfo::Smi();
329 case CompareIC::HEAP_NUMBERS: 322 case CompareIC::HEAP_NUMBER:
330 return TypeInfo::Number(); 323 return TypeInfo::Number();
331 case CompareIC::SYMBOLS: 324 case CompareIC::SYMBOL:
332 case CompareIC::STRINGS: 325 return TypeInfo::Symbol();
326 case CompareIC::STRING:
333 return TypeInfo::String(); 327 return TypeInfo::String();
334 case CompareIC::OBJECTS: 328 case CompareIC::OBJECT:
335 case CompareIC::KNOWN_OBJECTS: 329 case CompareIC::KNOWN_OBJECTS:
336 // TODO(kasperl): We really need a type for JS objects here. 330 // TODO(kasperl): We really need a type for JS objects here.
337 return TypeInfo::NonPrimitive(); 331 return TypeInfo::NonPrimitive();
338 case CompareIC::GENERIC: 332 case CompareIC::GENERIC:
339 default: 333 default:
340 return unknown; 334 return TypeInfo::Unknown();
341 } 335 }
342 } 336 }
343 337
344 338
345 bool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) { 339 void TypeFeedbackOracle::CompareType(CompareOperation* expr,
340 TypeInfo* left_type,
341 TypeInfo* right_type,
342 TypeInfo* overall_type) {
346 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); 343 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
347 if (!object->IsCode()) return false; 344 TypeInfo unknown = TypeInfo::Unknown();
345 if (!object->IsCode()) {
346 *left_type = *right_type = *overall_type = unknown;
347 return;
348 }
348 Handle<Code> code = Handle<Code>::cast(object); 349 Handle<Code> code = Handle<Code>::cast(object);
349 if (!code->is_compare_ic_stub()) return false; 350 if (!code->is_compare_ic_stub()) {
350 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 351 *left_type = *right_type = *overall_type = unknown;
351 return state == CompareIC::SYMBOLS; 352 return;
353 }
354
355 int stub_minor_key = code->stub_info();
356 CompareIC::State left_state, right_state, handler_state;
357 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
358 &handler_state, NULL);
359 *left_type = TypeFromCompareType(left_state);
360 *right_type = TypeFromCompareType(right_state);
361 *overall_type = TypeFromCompareType(handler_state);
352 } 362 }
353 363
354 364
355 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { 365 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
356 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); 366 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
357 if (!object->IsCode()) return Handle<Map>::null(); 367 if (!object->IsCode()) return Handle<Map>::null();
358 Handle<Code> code = Handle<Code>::cast(object); 368 Handle<Code> code = Handle<Code>::cast(object);
359 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); 369 if (!code->is_compare_ic_stub()) return Handle<Map>::null();
360 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 370 CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
361 if (state != CompareIC::KNOWN_OBJECTS) { 371 if (state != CompareIC::KNOWN_OBJECTS) {
362 return Handle<Map>::null(); 372 return Handle<Map>::null();
363 } 373 }
364 Map* first_map = code->FindFirstMap(); 374 Map* first_map = code->FindFirstMap();
365 ASSERT(first_map != NULL); 375 ASSERT(first_map != NULL);
366 return CanRetainOtherContext(first_map, *native_context_) 376 return CanRetainOtherContext(first_map, *native_context_)
367 ? Handle<Map>::null() 377 ? Handle<Map>::null()
368 : Handle<Map>(first_map); 378 : Handle<Map>(first_map);
369 } 379 }
370 380
(...skipping 10 matching lines...) Expand all
381 case UnaryOpIC::SMI: 391 case UnaryOpIC::SMI:
382 return TypeInfo::Smi(); 392 return TypeInfo::Smi();
383 case UnaryOpIC::HEAP_NUMBER: 393 case UnaryOpIC::HEAP_NUMBER:
384 return TypeInfo::Double(); 394 return TypeInfo::Double();
385 default: 395 default:
386 return unknown; 396 return unknown;
387 } 397 }
388 } 398 }
389 399
390 400
391 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { 401 static TypeInfo TypeFromBinaryOpType(BinaryOpIC::TypeInfo binary_type) {
392 Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId()); 402 switch (binary_type) {
393 TypeInfo unknown = TypeInfo::Unknown(); 403 // Uninitialized means never executed.
394 if (!object->IsCode()) return unknown; 404 case BinaryOpIC::UNINITIALIZED: return TypeInfo::Uninitialized();
395 Handle<Code> code = Handle<Code>::cast(object); 405 case BinaryOpIC::SMI: return TypeInfo::Smi();
396 if (code->is_binary_op_stub()) { 406 case BinaryOpIC::INT32: return TypeInfo::Integer32();
397 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 407 case BinaryOpIC::HEAP_NUMBER: return TypeInfo::Double();
398 code->binary_op_type()); 408 case BinaryOpIC::ODDBALL: return TypeInfo::Unknown();
399 BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>( 409 case BinaryOpIC::STRING: return TypeInfo::String();
400 code->binary_op_result_type()); 410 case BinaryOpIC::GENERIC: return TypeInfo::Unknown();
401
402 switch (type) {
403 case BinaryOpIC::UNINITIALIZED:
404 // Uninitialized means never executed.
405 return TypeInfo::Uninitialized();
406 case BinaryOpIC::SMI:
407 switch (result_type) {
408 case BinaryOpIC::UNINITIALIZED:
409 if (expr->op() == Token::DIV) {
410 return TypeInfo::Double();
411 }
412 return TypeInfo::Smi();
413 case BinaryOpIC::SMI:
414 return TypeInfo::Smi();
415 case BinaryOpIC::INT32:
416 return TypeInfo::Integer32();
417 case BinaryOpIC::HEAP_NUMBER:
418 return TypeInfo::Double();
419 default:
420 return unknown;
421 }
422 case BinaryOpIC::INT32:
423 if (expr->op() == Token::DIV ||
424 result_type == BinaryOpIC::HEAP_NUMBER) {
425 return TypeInfo::Double();
426 }
427 return TypeInfo::Integer32();
428 case BinaryOpIC::HEAP_NUMBER:
429 return TypeInfo::Double();
430 case BinaryOpIC::BOTH_STRING:
431 return TypeInfo::String();
432 case BinaryOpIC::STRING:
433 case BinaryOpIC::GENERIC:
434 return unknown;
435 default:
436 return unknown;
437 }
438 } 411 }
439 return unknown; 412 UNREACHABLE();
413 return TypeInfo::Unknown();
440 } 414 }
441 415
442 416
417 void TypeFeedbackOracle::BinaryType(BinaryOperation* expr,
418 TypeInfo* left,
419 TypeInfo* right,
420 TypeInfo* result) {
421 Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId());
422 TypeInfo unknown = TypeInfo::Unknown();
423 if (!object->IsCode()) {
424 *left = *right = *result = unknown;
425 return;
426 }
427 Handle<Code> code = Handle<Code>::cast(object);
428 if (code->is_binary_op_stub()) {
429 BinaryOpIC::TypeInfo left_type, right_type, result_type;
430 BinaryOpStub::decode_types_from_minor_key(code->stub_info(), &left_type,
431 &right_type, &result_type);
432 *left = TypeFromBinaryOpType(left_type);
433 *right = TypeFromBinaryOpType(right_type);
434 *result = TypeFromBinaryOpType(result_type);
435 return;
436 }
437 // Not a binary op stub.
438 *left = *right = *result = unknown;
439 }
440
441
443 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { 442 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
444 Handle<Object> object = GetInfo(clause->CompareId()); 443 Handle<Object> object = GetInfo(clause->CompareId());
445 TypeInfo unknown = TypeInfo::Unknown(); 444 TypeInfo unknown = TypeInfo::Unknown();
446 if (!object->IsCode()) return unknown; 445 if (!object->IsCode()) return unknown;
447 Handle<Code> code = Handle<Code>::cast(object); 446 Handle<Code> code = Handle<Code>::cast(object);
448 if (!code->is_compare_ic_stub()) return unknown; 447 if (!code->is_compare_ic_stub()) return unknown;
449 448
450 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 449 CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
451 switch (state) { 450 return TypeFromCompareType(state);
452 case CompareIC::UNINITIALIZED:
453 // Uninitialized means never executed.
454 // TODO(fschneider): Introduce a separate value for never-executed ICs.
455 return unknown;
456 case CompareIC::SMIS:
457 return TypeInfo::Smi();
458 case CompareIC::STRINGS:
459 return TypeInfo::String();
460 case CompareIC::SYMBOLS:
461 return TypeInfo::Symbol();
462 case CompareIC::HEAP_NUMBERS:
463 return TypeInfo::Number();
464 case CompareIC::OBJECTS:
465 case CompareIC::KNOWN_OBJECTS:
466 // TODO(kasperl): We really need a type for JS objects here.
467 return TypeInfo::NonPrimitive();
468 case CompareIC::GENERIC:
469 default:
470 return unknown;
471 }
472 } 451 }
473 452
474 453
475 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { 454 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
476 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); 455 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId());
477 TypeInfo unknown = TypeInfo::Unknown(); 456 TypeInfo unknown = TypeInfo::Unknown();
478 if (!object->IsCode()) return unknown; 457 if (!object->IsCode()) return unknown;
479 Handle<Code> code = Handle<Code>::cast(object); 458 Handle<Code> code = Handle<Code>::cast(object);
480 if (!code->is_binary_op_stub()) return unknown; 459 if (!code->is_binary_op_stub()) return unknown;
481 460
482 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 461 BinaryOpIC::TypeInfo left_type, right_type, unused_result_type;
483 code->binary_op_type()); 462 BinaryOpStub::decode_types_from_minor_key(code->stub_info(), &left_type,
484 switch (type) { 463 &right_type, &unused_result_type);
464 // CountOperations should always have +1 or -1 as their right input.
465 ASSERT(right_type == BinaryOpIC::SMI ||
466 right_type == BinaryOpIC::UNINITIALIZED);
467
468 switch (left_type) {
485 case BinaryOpIC::UNINITIALIZED: 469 case BinaryOpIC::UNINITIALIZED:
486 case BinaryOpIC::SMI: 470 case BinaryOpIC::SMI:
487 return TypeInfo::Smi(); 471 return TypeInfo::Smi();
488 case BinaryOpIC::INT32: 472 case BinaryOpIC::INT32:
489 return TypeInfo::Integer32(); 473 return TypeInfo::Integer32();
490 case BinaryOpIC::HEAP_NUMBER: 474 case BinaryOpIC::HEAP_NUMBER:
491 return TypeInfo::Double(); 475 return TypeInfo::Double();
492 case BinaryOpIC::BOTH_STRING:
493 case BinaryOpIC::STRING: 476 case BinaryOpIC::STRING:
494 case BinaryOpIC::GENERIC: 477 case BinaryOpIC::GENERIC:
495 return unknown; 478 return unknown;
496 default: 479 default:
497 return unknown; 480 return unknown;
498 } 481 }
499 UNREACHABLE(); 482 UNREACHABLE();
500 return unknown; 483 return unknown;
501 } 484 }
502 485
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 USE(maybe_result); 711 USE(maybe_result);
729 #ifdef DEBUG 712 #ifdef DEBUG
730 Object* result = NULL; 713 Object* result = NULL;
731 // Dictionary has been allocated with sufficient size for all elements. 714 // Dictionary has been allocated with sufficient size for all elements.
732 ASSERT(maybe_result->ToObject(&result)); 715 ASSERT(maybe_result->ToObject(&result));
733 ASSERT(*dictionary_ == result); 716 ASSERT(*dictionary_ == result);
734 #endif 717 #endif
735 } 718 }
736 719
737 } } // namespace v8::internal 720 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | src/x64/code-stubs-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698