368
385
Code* StackFrame::GetSafepointData(Isolate* isolate,
386
Address inner_pointer,
370
387
SafepointEntry* safepoint_entry,
371
388
unsigned* stack_slots) {
372
PcToCodeCache::PcToCodeCacheEntry* entry =
373
isolate->pc_to_code_cache()->GetCacheEntry(pc);
389
InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
390
isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
374
391
if (!entry->safepoint_entry.is_valid()) {
375
entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
392
entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
376
393
ASSERT(entry->safepoint_entry.is_valid());
378
ASSERT(entry->safepoint_entry.Equals(entry->code->GetSafepointEntry(pc)));
395
ASSERT(entry->safepoint_entry.Equals(
396
entry->code->GetSafepointEntry(inner_pointer)));
381
399
// Fill in the results and return the code.
759
void JavaScriptFrame::PrintTop(FILE* file,
761
bool print_line_number) {
764
AssertNoAllocation no_allocation;
765
JavaScriptFrameIterator it;
767
if (it.frame()->is_java_script()) {
768
JavaScriptFrame* frame = it.frame();
769
if (frame->IsConstructor()) PrintF(file, "new ");
771
Object* maybe_fun = frame->function();
772
if (maybe_fun->IsJSFunction()) {
773
JSFunction* fun = JSFunction::cast(maybe_fun);
775
Code* js_code = frame->unchecked_code();
776
Address pc = frame->pc();
778
static_cast<int>(pc - js_code->instruction_start());
779
PrintF("+%d", code_offset);
780
SharedFunctionInfo* shared = fun->shared();
781
if (print_line_number) {
782
Code* code = Code::cast(
783
v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
784
int source_pos = code->SourcePosition(pc);
785
Object* maybe_script = shared->script();
786
if (maybe_script->IsScript()) {
787
Handle<Script> script(Script::cast(maybe_script));
788
int line = GetScriptLineNumberSafe(script, source_pos) + 1;
789
Object* script_name_raw = script->name();
790
if (script_name_raw->IsString()) {
791
String* script_name = String::cast(script->name());
792
SmartArrayPointer<char> c_script_name =
793
script_name->ToCString(DISALLOW_NULLS,
794
ROBUST_STRING_TRAVERSAL);
795
PrintF(file, " at %s:%d", *c_script_name, line);
797
PrintF(file, " at <unknown>:%d", line);
800
PrintF(file, " at <unknown>:<unknown>");
808
// function arguments
809
// (we are intentionally only printing the actually
810
// supplied parameters, not all parameters required)
811
PrintF(file, "(this=");
812
frame->receiver()->ShortPrint(file);
813
const int length = frame->ComputeParametersCount();
814
for (int i = 0; i < length; i++) {
816
frame->GetParameter(i)->ShortPrint(file);
708
827
void FrameSummary::Print() {
709
828
PrintF("receiver: ");
710
829
receiver_->ShortPrint();
739
869
data->TranslationIndex(deopt_index)->value());
740
870
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
741
871
ASSERT(opcode == Translation::BEGIN);
742
int frame_count = it.Next();
872
it.Next(); // Drop frame count.
873
int jsframe_count = it.Next();
744
875
// We create the summary in reverse order because the frames
745
876
// in the deoptimization translation are ordered bottom-to-top.
877
bool is_constructor = IsConstructor();
878
int i = jsframe_count;
748
880
opcode = static_cast<Translation::Opcode>(it.Next());
749
if (opcode == Translation::FRAME) {
750
// We don't inline constructor calls, so only the first, outermost
751
// frame can be a constructor frame in case of inlining.
752
bool is_constructor = (i == frame_count) && IsConstructor();
881
if (opcode == Translation::JS_FRAME) {
755
int ast_id = it.Next();
756
int function_id = it.Next();
883
BailoutId ast_id = BailoutId(it.Next());
884
JSFunction* function = LiteralAt(literal_array, it.Next());
757
885
it.Next(); // Skip height.
758
JSFunction* function =
759
JSFunction::cast(data->LiteralArray()->get(function_id));
761
887
// The translation commands are ordered and the receiver is always
762
888
// at the first position. Since we are always at a call when we need
855
990
int deopt_index = Safepoint::kNoDeoptimizationIndex;
856
991
DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
992
FixedArray* literal_array = data->LiteralArray();
858
994
TranslationIterator it(data->TranslationByteArray(),
859
995
data->TranslationIndex(deopt_index)->value());
860
996
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
861
997
ASSERT(opcode == Translation::BEGIN);
862
int frame_count = it.Next();
998
it.Next(); // Drop frame count.
999
int jsframe_count = it.Next();
864
1001
// We insert the frames in reverse order because the frames
865
1002
// in the deoptimization translation are ordered bottom-to-top.
866
while (frame_count > 0) {
1003
while (jsframe_count > 0) {
867
1004
opcode = static_cast<Translation::Opcode>(it.Next());
868
if (opcode == Translation::FRAME) {
1005
if (opcode == Translation::JS_FRAME) {
870
1007
it.Next(); // Skip ast id.
871
int function_id = it.Next();
1008
JSFunction* function = LiteralAt(literal_array, it.Next());
872
1009
it.Next(); // Skip height.
873
JSFunction* function =
874
JSFunction::cast(data->LiteralArray()->get(function_id));
875
1010
functions->Add(function);
877
1012
// Skip over operands to advance to the next opcode.
927
1067
if (IsConstructor()) accumulator->Add("new ");
928
1068
accumulator->PrintFunction(function, receiver, &code);
930
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
1070
// Get scope information for nicer output, if possible. If code is NULL, or
1071
// doesn't contain scope info, scope_info will return 0 for the number of
1072
// parameters, stack local variables, context local variables, stack slots,
1073
// or context slots.
1074
Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
932
1076
if (function->IsJSFunction()) {
933
1077
Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
934
scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
1078
scope_info = Handle<ScopeInfo>(shared->scope_info());
935
1079
Object* script_obj = shared->script();
936
1080
if (script_obj->IsScript()) {
937
1081
Handle<Script> script(Script::cast(script_obj));
1016
1155
// Print heap-allocated local variables.
1017
if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
1156
if (heap_locals_count > 0) {
1018
1157
accumulator->Add(" // heap-allocated locals\n");
1020
for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
1159
for (int i = 0; i < heap_locals_count; i++) {
1021
1160
accumulator->Add(" var ");
1022
accumulator->PrintName(*info.context_slot_name(i));
1161
accumulator->PrintName(scope_info->ContextLocalName(i));
1023
1162
accumulator->Add(" = ");
1024
1163
if (context != NULL) {
1025
1164
if (i < context->length()) {
1026
accumulator->Add("%o", context->get(i));
1165
accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
1028
1167
accumulator->Add(
1029
1168
"// warning: missing context slot - inconsistent frame?");
1155
1294
// -------------------------------------------------------------------------
1158
Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) {
1297
static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1298
MapWord map_word = object->map_word();
1299
return map_word.IsForwardingAddress() ?
1300
map_word.ToForwardingAddress()->map() : map_word.ToMap();
1304
static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1305
return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1310
static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1311
Map* map = GcSafeMapOfCodeSpaceObject(code);
1312
ASSERT(map == code->GetHeap()->code_map());
1313
Address start = code->address();
1314
Address end = code->address() + code->SizeFromMap(map);
1315
return start <= addr && addr < end;
1320
Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1321
Address inner_pointer) {
1159
1322
Code* code = reinterpret_cast<Code*>(object);
1160
ASSERT(code != NULL && code->contains(pc));
1323
ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
1165
Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) {
1328
Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1329
Address inner_pointer) {
1166
1330
Heap* heap = isolate_->heap();
1167
// Check if the pc points into a large object chunk.
1168
LargeObjectChunk* chunk = heap->lo_space()->FindChunkContainingPc(pc);
1169
if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc);
1171
// Iterate through the 8K page until we reach the end or find an
1172
// object starting after the pc.
1173
Page* page = Page::FromAddress(pc);
1174
HeapObjectIterator iterator(page, heap->GcSafeSizeOfOldObjectFunction());
1175
HeapObject* previous = NULL;
1331
// Check if the inner pointer points into a large object chunk.
1332
LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1333
if (large_page != NULL) {
1334
return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1337
// Iterate through the page until we reach the end or find an object starting
1338
// after the inner pointer.
1339
Page* page = Page::FromAddress(inner_pointer);
1341
Address addr = page->skip_list()->StartFor(inner_pointer);
1343
Address top = heap->code_space()->top();
1344
Address limit = heap->code_space()->limit();
1177
HeapObject* next = iterator.next();
1178
if (next == NULL || next->address() >= pc) {
1179
return GcSafeCastToCode(previous, pc);
1347
if (addr == top && addr != limit) {
1352
HeapObject* obj = HeapObject::FromAddress(addr);
1353
int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1354
Address next_addr = addr + obj_size;
1355
if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1186
PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
1361
InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
1362
InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
1187
1363
isolate_->counters()->pc_to_code()->Increment();
1188
ASSERT(IsPowerOf2(kPcToCodeCacheSize));
1364
ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
1189
1365
uint32_t hash = ComputeIntegerHash(
1190
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)),
1366
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1191
1367
v8::internal::kZeroHashSeed);
1192
uint32_t index = hash & (kPcToCodeCacheSize - 1);
1193
PcToCodeCacheEntry* entry = cache(index);
1194
if (entry->pc == pc) {
1368
uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1369
InnerPointerToCodeCacheEntry* entry = cache(index);
1370
if (entry->inner_pointer == inner_pointer) {
1195
1371
isolate_->counters()->pc_to_code_cached()->Increment();
1196
ASSERT(entry->code == GcSafeFindCodeForPc(pc));
1372
ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
1198
1374
// Because this code may be interrupted by a profiling signal that
1199
// also queries the cache, we cannot update pc before the code has
1200
// been set. Otherwise, we risk trying to use a cache entry before
1375
// also queries the cache, we cannot update inner_pointer before the code
1376
// has been set. Otherwise, we risk trying to use a cache entry before
1201
1377
// the code has been computed.
1202
entry->code = GcSafeFindCodeForPc(pc);
1378
entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
1203
1379
entry->safepoint_entry.Reset();
1380
entry->inner_pointer = inner_pointer;
1210
1386
// -------------------------------------------------------------------------
1212
1388
int NumRegs(RegList reglist) {
1214
while (reglist != 0) {
1216
reglist &= reglist - 1; // clear one bit
1389
return CompilerIntrinsics::CountSetBits(reglist);
1222
1393
struct JSCallerSavedCodeData {
1223
JSCallerSavedCodeData() {
1225
for (int r = 0; r < kNumRegs; r++)
1226
if ((kJSCallerSaved & (1 << r)) != 0)
1229
ASSERT(i == kNumJSCallerSaved);
1231
1394
int reg_code[kNumJSCallerSaved];
1235
static const JSCallerSavedCodeData kCallerSavedCodeData;
1397
JSCallerSavedCodeData caller_saved_code_data;
1399
void SetUpJSCallerSavedCodeData() {
1401
for (int r = 0; r < kNumRegs; r++)
1402
if ((kJSCallerSaved & (1 << r)) != 0)
1403
caller_saved_code_data.reg_code[i++] = r;
1405
ASSERT(i == kNumJSCallerSaved);
1238
1408
int JSCallerSavedCode(int n) {
1239
1409
ASSERT(0 <= n && n < kNumJSCallerSaved);
1240
return kCallerSavedCodeData.reg_code[n];
1410
return caller_saved_code_data.reg_code[n];