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

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: HConstants, HSimulates, stub fixes 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
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);
362 if (left_type->IsUninitialized() && right_type->IsUninitialized() &&
363 overall_type->IsUninitialized()) {
364 // All CompareICs have inlined Smi code, so there's a good chance
365 // that inlined Smi code has handled everything. Assume Smi type feedback.
366 *left_type = *right_type = *overall_type = TypeInfo::Smi();
367 }
352 } 368 }
353 369
354 370
355 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { 371 Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
356 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId()); 372 Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
357 if (!object->IsCode()) return Handle<Map>::null(); 373 if (!object->IsCode()) return Handle<Map>::null();
358 Handle<Code> code = Handle<Code>::cast(object); 374 Handle<Code> code = Handle<Code>::cast(object);
359 if (!code->is_compare_ic_stub()) return Handle<Map>::null(); 375 if (!code->is_compare_ic_stub()) return Handle<Map>::null();
360 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 376 CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
361 if (state != CompareIC::KNOWN_OBJECTS) { 377 if (state != CompareIC::KNOWN_OBJECTS) {
362 return Handle<Map>::null(); 378 return Handle<Map>::null();
363 } 379 }
364 Map* first_map = code->FindFirstMap(); 380 Map* first_map = code->FindFirstMap();
365 ASSERT(first_map != NULL); 381 ASSERT(first_map != NULL);
366 return CanRetainOtherContext(first_map, *native_context_) 382 return CanRetainOtherContext(first_map, *native_context_)
367 ? Handle<Map>::null() 383 ? Handle<Map>::null()
368 : Handle<Map>(first_map); 384 : Handle<Map>(first_map);
369 } 385 }
370 386
(...skipping 10 matching lines...) Expand all
381 case UnaryOpIC::SMI: 397 case UnaryOpIC::SMI:
382 return TypeInfo::Smi(); 398 return TypeInfo::Smi();
383 case UnaryOpIC::HEAP_NUMBER: 399 case UnaryOpIC::HEAP_NUMBER:
384 return TypeInfo::Double(); 400 return TypeInfo::Double();
385 default: 401 default:
386 return unknown; 402 return unknown;
387 } 403 }
388 } 404 }
389 405
390 406
391 TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { 407 static TypeInfo TypeFromBinaryOpType(BinaryOpIC::TypeInfo binary_type) {
392 Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId()); 408 switch (binary_type) {
393 TypeInfo unknown = TypeInfo::Unknown(); 409 // Uninitialized means never executed.
394 if (!object->IsCode()) return unknown; 410 case BinaryOpIC::UNINITIALIZED: return TypeInfo::Uninitialized();
395 Handle<Code> code = Handle<Code>::cast(object); 411 case BinaryOpIC::SMI: return TypeInfo::Smi();
396 if (code->is_binary_op_stub()) { 412 case BinaryOpIC::INT32: return TypeInfo::Integer32();
397 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 413 case BinaryOpIC::HEAP_NUMBER: return TypeInfo::Double();
398 code->binary_op_type()); 414 case BinaryOpIC::ODDBALL: return TypeInfo::Unknown();
399 BinaryOpIC::TypeInfo result_type = static_cast<BinaryOpIC::TypeInfo>( 415 case BinaryOpIC::STRING: return TypeInfo::String();
400 code->binary_op_result_type()); 416 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 } 417 }
439 return unknown; 418 UNREACHABLE();
419 return TypeInfo::Unknown();
440 } 420 }
441 421
442 422
423 static TypeInfo BinaryOpResultType(BinaryOpIC::TypeInfo result_type,
424 BinaryOpIC::TypeInfo left_type,
425 BinaryOpIC::TypeInfo right_type,
426 Token::Value op) {
427 if (result_type == BinaryOpIC::UNINITIALIZED) {
428 if (op == Token::DIV) return TypeInfo::Double();
429 return TypeFromBinaryOpType(Max(left_type, right_type));
430 }
431 return TypeFromBinaryOpType(result_type);
432 }
433
434
435 void TypeFeedbackOracle::BinaryType(BinaryOperation* expr,
436 TypeInfo* left,
437 TypeInfo* right,
438 TypeInfo* result) {
439 Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId());
440 TypeInfo unknown = TypeInfo::Unknown();
441 if (!object->IsCode()) {
442 *left = *right = *result = unknown;
443 return;
444 }
445 Handle<Code> code = Handle<Code>::cast(object);
446 if (code->is_binary_op_stub()) {
447 BinaryOpIC::TypeInfo left_type, right_type, result_type;
448 BinaryOpStub::decode_types_from_minor_key(code->stub_info(), &left_type,
449 &right_type, &result_type);
450 Token::Value op = expr->op();
451 *left = TypeFromBinaryOpType(left_type);
452 *right = TypeFromBinaryOpType(right_type);
453 *result = BinaryOpResultType(result_type, left_type, right_type, op);
454 return;
455 }
456 // Not a binary op stub.
457 *left = *right = *result = unknown;
458 }
459
460
443 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { 461 TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
444 Handle<Object> object = GetInfo(clause->CompareId()); 462 Handle<Object> object = GetInfo(clause->CompareId());
445 TypeInfo unknown = TypeInfo::Unknown(); 463 TypeInfo unknown = TypeInfo::Unknown();
446 if (!object->IsCode()) return unknown; 464 if (!object->IsCode()) return unknown;
447 Handle<Code> code = Handle<Code>::cast(object); 465 Handle<Code> code = Handle<Code>::cast(object);
448 if (!code->is_compare_ic_stub()) return unknown; 466 if (!code->is_compare_ic_stub()) return unknown;
449 467
450 CompareIC::State state = static_cast<CompareIC::State>(code->compare_state()); 468 CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
451 switch (state) { 469 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 } 470 }
473 471
474 472
475 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { 473 TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
476 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId()); 474 Handle<Object> object = GetInfo(expr->CountBinOpFeedbackId());
477 TypeInfo unknown = TypeInfo::Unknown(); 475 TypeInfo unknown = TypeInfo::Unknown();
478 if (!object->IsCode()) return unknown; 476 if (!object->IsCode()) return unknown;
479 Handle<Code> code = Handle<Code>::cast(object); 477 Handle<Code> code = Handle<Code>::cast(object);
480 if (!code->is_binary_op_stub()) return unknown; 478 if (!code->is_binary_op_stub()) return unknown;
481 479
482 BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>( 480 BinaryOpIC::TypeInfo left_type, right_type, unused_result_type;
483 code->binary_op_type()); 481 BinaryOpStub::decode_types_from_minor_key(code->stub_info(), &left_type,
484 switch (type) { 482 &right_type, &unused_result_type);
483 // CountOperations should always have +1 or -1 as their right input.
484 ASSERT(right_type == BinaryOpIC::SMI ||
485 right_type == BinaryOpIC::UNINITIALIZED);
486
487 switch (left_type) {
485 case BinaryOpIC::UNINITIALIZED: 488 case BinaryOpIC::UNINITIALIZED:
486 case BinaryOpIC::SMI: 489 case BinaryOpIC::SMI:
487 return TypeInfo::Smi(); 490 return TypeInfo::Smi();
488 case BinaryOpIC::INT32: 491 case BinaryOpIC::INT32:
489 return TypeInfo::Integer32(); 492 return TypeInfo::Integer32();
490 case BinaryOpIC::HEAP_NUMBER: 493 case BinaryOpIC::HEAP_NUMBER:
491 return TypeInfo::Double(); 494 return TypeInfo::Double();
492 case BinaryOpIC::BOTH_STRING:
493 case BinaryOpIC::STRING: 495 case BinaryOpIC::STRING:
494 case BinaryOpIC::GENERIC: 496 case BinaryOpIC::GENERIC:
495 return unknown; 497 return unknown;
496 default: 498 default:
497 return unknown; 499 return unknown;
498 } 500 }
499 UNREACHABLE(); 501 UNREACHABLE();
500 return unknown; 502 return unknown;
501 } 503 }
502 504
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 USE(maybe_result); 730 USE(maybe_result);
729 #ifdef DEBUG 731 #ifdef DEBUG
730 Object* result = NULL; 732 Object* result = NULL;
731 // Dictionary has been allocated with sufficient size for all elements. 733 // Dictionary has been allocated with sufficient size for all elements.
732 ASSERT(maybe_result->ToObject(&result)); 734 ASSERT(maybe_result->ToObject(&result));
733 ASSERT(*dictionary_ == result); 735 ASSERT(*dictionary_ == result);
734 #endif 736 #endif
735 } 737 }
736 738
737 } } // namespace v8::internal 739 } } // namespace v8::internal
OLDNEW
« src/objects-inl.h ('K') | « 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