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

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

Issue 7204003: Refactor the way we collect the information for associating type-related infos (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 6 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
« no previous file with comments | « src/type-info.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 } else { 54 } else {
55 info = TypeInfo::Unknown(); 55 info = TypeInfo::Unknown();
56 } 56 }
57 return info; 57 return info;
58 } 58 }
59 59
60 60
61 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, 61 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
62 Handle<Context> global_context) { 62 Handle<Context> global_context) {
63 global_context_ = global_context; 63 global_context_ = global_context;
64 PopulateMap(code); 64 BuildDictionary(code);
65 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue); 65 ASSERT(reinterpret_cast<Address>(*dictionary_.location()) != kHandleZapValue);
66 } 66 }
67 67
68 68
69 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { 69 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) {
70 int entry = dictionary_->FindEntry(ast_id); 70 int entry = dictionary_->FindEntry(ast_id);
71 return entry != NumberDictionary::kNotFound 71 return entry != NumberDictionary::kNotFound
72 ? Handle<Object>(dictionary_->ValueAt(entry)) 72 ? Handle<Object>(dictionary_->ValueAt(entry))
73 : Isolate::Current()->factory()->undefined_value(); 73 : Isolate::Current()->factory()->undefined_value();
74 } 74 }
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 ZoneMapList* types = new ZoneMapList(4); 383 ZoneMapList* types = new ZoneMapList(4);
384 ASSERT(object->IsCode()); 384 ASSERT(object->IsCode());
385 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags); 385 isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
386 return types->length() > 0 ? types : NULL; 386 return types->length() > 0 ? types : NULL;
387 } else { 387 } else {
388 return NULL; 388 return NULL;
389 } 389 }
390 } 390 }
391 391
392 392
393 // Things are a bit tricky here: The iterator for the RelocInfos and the infos
394 // themselves are not GC-safe, so we first get all infos, then we create the
395 // dictionary (possibly triggering GC), and finally we relocate the collected
396 // infos before we process them.
397 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) {
398 AssertNoAllocation no_allocation;
399 HandleScope scope;
400 List<RelocInfo> infos(16);
401 GetRelocInfos(code, &infos);
402 CreateDictionary(code, &infos);
403 ProcessRelocInfos(&infos);
404 // Allocate handle in the parent scope.
405 dictionary_ = scope.CloseAndEscape(dictionary_);
406 }
407
408
409 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
410 List<RelocInfo>* infos) {
411 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
412 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
413 infos->Add(*it.rinfo());
414 }
415 }
416
417
418 void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
419 List<RelocInfo>* infos) {
420 DisableAssertNoAllocation allocation_allowed;
421 byte* old_start = (*code)->instruction_start();
Mads Ager (chromium) 2011/06/20 08:57:38 You shouldn't need the explicit dereference here?
Sven Panne 2011/06/20 10:16:20 Done.
422 dictionary_ = FACTORY->NewNumberDictionary(infos->length());
423 byte* new_start = (*code)->instruction_start();
Mads Ager (chromium) 2011/06/20 08:57:38 Ditto.
Sven Panne 2011/06/20 10:16:20 Done.
424 RelocateRelocInfos(infos, old_start, new_start);
425 }
426
427
428 void TypeFeedbackOracle::RelocateRelocInfos(List<RelocInfo>* infos,
429 byte* old_start,
430 byte* new_start) {
431 for (int i = 0; i < infos->length(); i++) {
432 RelocInfo* info = &(*infos)[i];
433 info->set_pc(new_start + (info->pc() - old_start));
434 }
435 }
436
437
438 void TypeFeedbackOracle::ProcessRelocInfos(List<RelocInfo>* infos) {
439 for (int i = 0; i < infos->length(); i++) {
440 unsigned ast_id = static_cast<unsigned>((*infos)[i].data());
441 Code* target = Code::GetCodeFromTargetAddress((*infos)[i].target_address());
442 ProcessTarget(ast_id, target);
443 }
444 }
445
446
447 void TypeFeedbackOracle::ProcessTarget(unsigned ast_id, Code* target) {
448 switch (target->kind()) {
449 case Code::LOAD_IC:
450 case Code::STORE_IC:
451 case Code::CALL_IC:
452 case Code::KEYED_CALL_IC:
453 if (target->ic_state() == MONOMORPHIC) {
454 if (target->kind() == Code::CALL_IC &&
455 target->check_type() != RECEIVER_MAP_CHECK) {
456 SetInfo(ast_id, Smi::FromInt(target->check_type()));
457 } else {
458 Object* map = target->FindFirstMap();
459 SetInfo(ast_id, map == NULL ? static_cast<Object*>(target) : map);
460 }
461 } else if (target->ic_state() == MEGAMORPHIC) {
462 SetInfo(ast_id, target);
463 }
464 break;
465
466 case Code::KEYED_LOAD_IC:
467 case Code::KEYED_STORE_IC:
468 if (target->ic_state() == MONOMORPHIC ||
469 target->ic_state() == MEGAMORPHIC) {
470 SetInfo(ast_id, target);
471 }
472 break;
473
474 case Code::UNARY_OP_IC:
475 case Code::BINARY_OP_IC:
476 case Code::COMPARE_IC:
477 SetInfo(ast_id, target);
Mads Ager (chromium) 2011/06/20 08:57:38 Didn't we have some filtering in the old code for
Sven Panne 2011/06/20 10:16:20 We *had* some filtering code here, but I removed i
478 break;
479
480 default:
481 break;
482 }
483 }
484
485
393 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { 486 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) {
394 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); 487 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound);
395 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); 488 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target);
396 USE(maybe_result); 489 USE(maybe_result);
397 #ifdef DEBUG 490 #ifdef DEBUG
398 Object* result = NULL; 491 Object* result = NULL;
399 // Dictionary has been allocated with sufficient size for all elements. 492 // Dictionary has been allocated with sufficient size for all elements.
400 ASSERT(maybe_result->ToObject(&result)); 493 ASSERT(maybe_result->ToObject(&result));
401 ASSERT(*dictionary_ == result); 494 ASSERT(*dictionary_ == result);
402 #endif 495 #endif
403 } 496 }
404 497
405
406 void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
407 Isolate* isolate = Isolate::Current();
408 HandleScope scope(isolate);
409
410 const int kInitialCapacity = 16;
411 List<int> code_positions(kInitialCapacity);
412 List<unsigned> ast_ids(kInitialCapacity);
413 CollectIds(*code, &code_positions, &ast_ids);
414
415 ASSERT(dictionary_.is_null()); // Only initialize once.
416 dictionary_ = isolate->factory()->NewNumberDictionary(
417 code_positions.length());
418
419 const int length = code_positions.length();
420 ASSERT(ast_ids.length() == length);
421 for (int i = 0; i < length; i++) {
422 AssertNoAllocation no_allocation;
423 RelocInfo info(code->instruction_start() + code_positions[i],
424 RelocInfo::CODE_TARGET, 0);
425 Code* target = Code::GetCodeFromTargetAddress(info.target_address());
426 unsigned id = ast_ids[i];
427 InlineCacheState state = target->ic_state();
428 Code::Kind kind = target->kind();
429
430 if (kind == Code::BINARY_OP_IC ||
431 kind == Code::UNARY_OP_IC ||
432 kind == Code::COMPARE_IC) {
433 SetInfo(id, target);
434 } else if (state == MONOMORPHIC) {
435 if (kind == Code::KEYED_LOAD_IC ||
436 kind == Code::KEYED_STORE_IC) {
437 SetInfo(id, target);
438 } else if (kind != Code::CALL_IC ||
439 target->check_type() == RECEIVER_MAP_CHECK) {
440 Map* map = target->FindFirstMap();
441 if (map == NULL) {
442 SetInfo(id, target);
443 } else {
444 SetInfo(id, map);
445 }
446 } else {
447 ASSERT(target->kind() == Code::CALL_IC);
448 CheckType check = target->check_type();
449 ASSERT(check != RECEIVER_MAP_CHECK);
450 SetInfo(id, Smi::FromInt(check));
451 }
452 } else if (state == MEGAMORPHIC) {
453 SetInfo(id, target);
454 }
455 }
456 // Allocate handle in the parent scope.
457 dictionary_ = scope.CloseAndEscape(dictionary_);
458 }
459
460
461 void TypeFeedbackOracle::CollectIds(Code* code,
462 List<int>* code_positions,
463 List<unsigned>* ast_ids) {
464 AssertNoAllocation no_allocation;
465 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
466 for (RelocIterator it(code, mask); !it.done(); it.next()) {
467 RelocInfo* info = it.rinfo();
468 ASSERT(RelocInfo::IsCodeTarget(info->rmode()));
469 Code* target = Code::GetCodeFromTargetAddress(info->target_address());
470 if (target->is_inline_cache_stub()) {
471 InlineCacheState state = target->ic_state();
472 Code::Kind kind = target->kind();
473 if (kind == Code::BINARY_OP_IC) {
474 if (target->binary_op_type() ==
475 BinaryOpIC::GENERIC) {
476 continue;
477 }
478 } else if (kind == Code::COMPARE_IC) {
479 if (target->compare_state() == CompareIC::GENERIC) continue;
480 } else {
481 if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
482 }
483 code_positions->Add(
484 static_cast<int>(info->pc() - code->instruction_start()));
485 ASSERT(ast_ids->length() == 0 ||
486 (*ast_ids)[ast_ids->length()-1] !=
487 static_cast<unsigned>(info->data()));
488 ast_ids->Add(static_cast<unsigned>(info->data()));
489 }
490 }
491 }
492
493 } } // namespace v8::internal 498 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698