説明を見る。00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "v8.h"
00036
00037 #include "arguments.h"
00038 #include "execution.h"
00039 #include "ic-inl.h"
00040 #include "factory.h"
00041 #include "runtime.h"
00042 #include "serialize.h"
00043 #include "stub-cache.h"
00044
00045 namespace v8 { namespace internal {
00046
00047
00048
00049
00050
00051 int Label::pos() const {
00052 if (pos_ < 0) return -pos_ - 1;
00053 if (pos_ > 0) return pos_ - 1;
00054 UNREACHABLE();
00055 return 0;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 const int kMaxRelocModes = 14;
00101
00102 const int kTagBits = 2;
00103 const int kTagMask = (1 << kTagBits) - 1;
00104 const int kExtraTagBits = 4;
00105 const int kPositionTypeTagBits = 1;
00106 const int kSmallDataBits = kBitsPerByte - kPositionTypeTagBits;
00107
00108 const int kEmbeddedObjectTag = 0;
00109 const int kCodeTargetTag = 1;
00110 const int kPositionTag = 2;
00111 const int kDefaultTag = 3;
00112
00113 const int kPCJumpTag = (1 << kExtraTagBits) - 1;
00114
00115 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
00116 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
00117
00118 const int kVariableLengthPCJumpTopTag = 1;
00119 const int kChunkBits = 7;
00120 const int kChunkMask = (1 << kChunkBits) - 1;
00121 const int kLastChunkTagBits = 1;
00122 const int kLastChunkTagMask = 1;
00123 const int kLastChunkTag = 1;
00124
00125
00126 const int kDataJumpTag = kPCJumpTag - 1;
00127
00128 const int kNonstatementPositionTag = 0;
00129 const int kStatementPositionTag = 1;
00130 const int kCommentTag = 2;
00131
00132
00133 uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
00134
00135
00136
00137 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
00138 WriteExtraTag(kPCJumpTag, kVariableLengthPCJumpTopTag);
00139 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
00140 ASSERT(pc_jump > 0);
00141
00142 for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
00143 byte b = pc_jump & kChunkMask;
00144 *--pos_ = b << kLastChunkTagBits;
00145 }
00146
00147 *pos_ = *pos_ | kLastChunkTag;
00148
00149 return pc_delta & kSmallPCDeltaMask;
00150 }
00151
00152
00153 void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
00154
00155 pc_delta = WriteVariableLengthPCJump(pc_delta);
00156 *--pos_ = pc_delta << kTagBits | tag;
00157 }
00158
00159
00160 void RelocInfoWriter::WriteTaggedData(int32_t data_delta, int tag) {
00161 *--pos_ = data_delta << kPositionTypeTagBits | tag;
00162 }
00163
00164
00165 void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
00166 *--pos_ = top_tag << (kTagBits + kExtraTagBits) |
00167 extra_tag << kTagBits |
00168 kDefaultTag;
00169 }
00170
00171
00172 void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
00173
00174 pc_delta = WriteVariableLengthPCJump(pc_delta);
00175 WriteExtraTag(extra_tag, 0);
00176 *--pos_ = pc_delta;
00177 }
00178
00179
00180 void RelocInfoWriter::WriteExtraTaggedData(int32_t data_delta, int top_tag) {
00181 WriteExtraTag(kDataJumpTag, top_tag);
00182 for (int i = 0; i < kIntSize; i++) {
00183 *--pos_ = data_delta;
00184 data_delta = ArithmeticShiftRight(data_delta, kBitsPerByte);
00185 }
00186 }
00187
00188
00189 void RelocInfoWriter::Write(const RelocInfo* rinfo) {
00190 #ifdef DEBUG
00191 byte* begin_pos = pos_;
00192 #endif
00193 Counters::reloc_info_count.Increment();
00194 ASSERT(rinfo->pc() - last_pc_ >= 0);
00195 ASSERT(RelocInfo::NUMBER_OF_MODES < kMaxRelocModes);
00196
00197 uint32_t pc_delta = rinfo->pc() - last_pc_;
00198 RelocInfo::Mode rmode = rinfo->rmode();
00199
00200
00201 if (rmode == RelocInfo::EMBEDDED_OBJECT) {
00202 WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
00203 } else if (rmode == RelocInfo::CODE_TARGET) {
00204 WriteTaggedPC(pc_delta, kCodeTargetTag);
00205 } else if (RelocInfo::IsPosition(rmode)) {
00206
00207 int32_t data_delta = rinfo->data() - last_data_;
00208 int pos_type_tag = rmode == RelocInfo::POSITION ? kNonstatementPositionTag
00209 : kStatementPositionTag;
00210
00211 if (is_intn(data_delta, kSmallDataBits)) {
00212 WriteTaggedPC(pc_delta, kPositionTag);
00213 WriteTaggedData(data_delta, pos_type_tag);
00214 last_data_ = rinfo->data();
00215 } else {
00216
00217 WriteExtraTaggedPC(pc_delta, kPCJumpTag);
00218 WriteExtraTaggedData(data_delta, pos_type_tag);
00219 last_data_ = rinfo->data();
00220 }
00221 } else if (RelocInfo::IsComment(rmode)) {
00222
00223 WriteExtraTaggedPC(pc_delta, kPCJumpTag);
00224 WriteExtraTaggedData(rinfo->data() - last_data_, kCommentTag);
00225 last_data_ = rinfo->data();
00226 } else {
00227
00228
00229 ASSERT(rmode < kPCJumpTag && rmode < kDataJumpTag);
00230 WriteExtraTaggedPC(pc_delta, rmode);
00231 }
00232 last_pc_ = rinfo->pc();
00233 #ifdef DEBUG
00234 ASSERT(begin_pos - pos_ <= kMaxSize);
00235 #endif
00236 }
00237
00238
00239 inline int RelocIterator::AdvanceGetTag() {
00240 return *--pos_ & kTagMask;
00241 }
00242
00243
00244 inline int RelocIterator::GetExtraTag() {
00245 return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
00246 }
00247
00248
00249 inline int RelocIterator::GetTopTag() {
00250 return *pos_ >> (kTagBits + kExtraTagBits);
00251 }
00252
00253
00254 inline void RelocIterator::ReadTaggedPC() {
00255 rinfo_.pc_ += *pos_ >> kTagBits;
00256 }
00257
00258
00259 inline void RelocIterator::AdvanceReadPC() {
00260 rinfo_.pc_ += *--pos_;
00261 }
00262
00263
00264 void RelocIterator::AdvanceReadData() {
00265 int32_t x = 0;
00266 for (int i = 0; i < kIntSize; i++) {
00267 x |= *--pos_ << i * kBitsPerByte;
00268 }
00269 rinfo_.data_ += x;
00270 }
00271
00272
00273 void RelocIterator::AdvanceReadVariableLengthPCJump() {
00274
00275
00276
00277 uint32_t pc_jump = 0;
00278 for (int i = 0; i < kIntSize; i++) {
00279 byte pc_jump_part = *--pos_;
00280 pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
00281 if ((pc_jump_part & kLastChunkTagMask) == 1) break;
00282 }
00283
00284
00285 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
00286 }
00287
00288
00289 inline int RelocIterator::GetPositionTypeTag() {
00290 return *pos_ & ((1 << kPositionTypeTagBits) - 1);
00291 }
00292
00293
00294 inline void RelocIterator::ReadTaggedData() {
00295 int8_t signed_b = *pos_;
00296 rinfo_.data_ += ArithmeticShiftRight(signed_b, kPositionTypeTagBits);
00297 }
00298
00299
00300 inline RelocInfo::Mode RelocIterator::DebugInfoModeFromTag(int tag) {
00301 if (tag == kStatementPositionTag) {
00302 return RelocInfo::STATEMENT_POSITION;
00303 } else if (tag == kNonstatementPositionTag) {
00304 return RelocInfo::POSITION;
00305 } else {
00306 ASSERT(tag == kCommentTag);
00307 return RelocInfo::COMMENT;
00308 }
00309 }
00310
00311
00312 void RelocIterator::next() {
00313 ASSERT(!done());
00314
00315
00316
00317
00318
00319 while (pos_ > end_) {
00320 int tag = AdvanceGetTag();
00321 if (tag == kEmbeddedObjectTag) {
00322 ReadTaggedPC();
00323 if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
00324 } else if (tag == kCodeTargetTag) {
00325 ReadTaggedPC();
00326 if (*(reinterpret_cast<int*>(rinfo_.pc())) == 0x61) {
00327 tag = 0;
00328 }
00329 if (SetMode(RelocInfo::CODE_TARGET)) return;
00330 } else if (tag == kPositionTag) {
00331 ReadTaggedPC();
00332 Advance();
00333
00334 if (mode_mask_ & RelocInfo::kPositionMask) {
00335
00336 if (SetMode(DebugInfoModeFromTag(GetPositionTypeTag()))) {
00337
00338 ReadTaggedData();
00339 return;
00340 }
00341 }
00342 } else {
00343 ASSERT(tag == kDefaultTag);
00344 int extra_tag = GetExtraTag();
00345 if (extra_tag == kPCJumpTag) {
00346 int top_tag = GetTopTag();
00347 if (top_tag == kVariableLengthPCJumpTopTag) {
00348 AdvanceReadVariableLengthPCJump();
00349 } else {
00350 AdvanceReadPC();
00351 }
00352 } else if (extra_tag == kDataJumpTag) {
00353
00354 if (mode_mask_ & RelocInfo::kDebugMask) {
00355 int top_tag = GetTopTag();
00356 AdvanceReadData();
00357 if (SetMode(DebugInfoModeFromTag(top_tag))) return;
00358 } else {
00359
00360 Advance(kIntSize);
00361 }
00362 } else {
00363 AdvanceReadPC();
00364 if (SetMode(static_cast<RelocInfo::Mode>(extra_tag))) return;
00365 }
00366 }
00367 }
00368 done_ = true;
00369 }
00370
00371
00372 RelocIterator::RelocIterator(Code* code, int mode_mask) {
00373 rinfo_.pc_ = code->instruction_start();
00374 rinfo_.data_ = 0;
00375
00376 pos_ = code->relocation_start() + code->relocation_size();
00377 end_ = code->relocation_start();
00378 done_ = false;
00379 mode_mask_ = mode_mask;
00380 if (mode_mask_ == 0) pos_ = end_;
00381 next();
00382 }
00383
00384
00385 RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
00386 rinfo_.pc_ = desc.buffer;
00387 rinfo_.data_ = 0;
00388
00389 pos_ = desc.buffer + desc.buffer_size;
00390 end_ = pos_ - desc.reloc_size;
00391 done_ = false;
00392 mode_mask_ = mode_mask;
00393 if (mode_mask_ == 0) pos_ = end_;
00394 next();
00395 }
00396
00397
00398
00399
00400
00401
00402 #ifdef ENABLE_DISASSEMBLER
00403 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
00404 switch (rmode) {
00405 case RelocInfo::NONE:
00406 return "no reloc";
00407 case RelocInfo::EMBEDDED_OBJECT:
00408 return "embedded object";
00409 case RelocInfo::EMBEDDED_STRING:
00410 return "embedded string";
00411 case RelocInfo::CONSTRUCT_CALL:
00412 return "code target (js construct call)";
00413 case RelocInfo::CODE_TARGET_CONTEXT:
00414 return "code target (context)";
00415 case RelocInfo::CODE_TARGET:
00416 return "code target";
00417 case RelocInfo::RUNTIME_ENTRY:
00418 return "runtime entry";
00419 case RelocInfo::JS_RETURN:
00420 return "js return";
00421 case RelocInfo::COMMENT:
00422 return "comment";
00423 case RelocInfo::POSITION:
00424 return "position";
00425 case RelocInfo::STATEMENT_POSITION:
00426 return "statement position";
00427 case RelocInfo::EXTERNAL_REFERENCE:
00428 return "external reference";
00429 case RelocInfo::INTERNAL_REFERENCE:
00430 return "internal reference";
00431 case RelocInfo::NUMBER_OF_MODES:
00432 UNREACHABLE();
00433 return "number_of_modes";
00434 }
00435 return "unknown relocation type";
00436 }
00437
00438
00439 void RelocInfo::Print() {
00440 PrintF("%p %s", pc_, RelocModeName(rmode_));
00441 if (IsComment(rmode_)) {
00442 PrintF(" (%s)", data_);
00443 } else if (rmode_ == EMBEDDED_OBJECT) {
00444 PrintF(" (");
00445 target_object()->ShortPrint();
00446 PrintF(")");
00447 } else if (rmode_ == EXTERNAL_REFERENCE) {
00448 ExternalReferenceEncoder ref_encoder;
00449 PrintF(" (%s) (%p)",
00450 ref_encoder.NameOfAddress(*target_reference_address()),
00451 *target_reference_address());
00452 } else if (IsCodeTarget(rmode_)) {
00453 Code* code = Debug::GetCodeTarget(target_address());
00454 PrintF(" (%s) (%p)", Code::Kind2String(code->kind()), target_address());
00455 } else if (IsPosition(rmode_)) {
00456 PrintF(" (%d)", data());
00457 }
00458
00459 PrintF("\n");
00460 }
00461 #endif // ENABLE_DISASSEMBLER
00462
00463
00464 #ifdef DEBUG
00465 void RelocInfo::Verify() {
00466 switch (rmode_) {
00467 case EMBEDDED_OBJECT:
00468 Object::VerifyPointer(target_object());
00469 break;
00470 case CONSTRUCT_CALL:
00471 case CODE_TARGET_CONTEXT:
00472 case CODE_TARGET: {
00473
00474 Address addr = target_address();
00475 ASSERT(addr != NULL);
00476
00477 HeapObject* code = HeapObject::FromAddress(addr - Code::kHeaderSize);
00478 Object* found = Heap::FindCodeObject(addr);
00479 ASSERT(found->IsCode());
00480 ASSERT(code->address() == HeapObject::cast(found)->address());
00481 break;
00482 }
00483 case RelocInfo::EMBEDDED_STRING:
00484 case RUNTIME_ENTRY:
00485 case JS_RETURN:
00486 case COMMENT:
00487 case POSITION:
00488 case STATEMENT_POSITION:
00489 case EXTERNAL_REFERENCE:
00490 case INTERNAL_REFERENCE:
00491 case NONE:
00492 break;
00493 case NUMBER_OF_MODES:
00494 UNREACHABLE();
00495 break;
00496 }
00497 }
00498 #endif // DEBUG
00499
00500
00501
00502
00503
00504 ExternalReference::ExternalReference(Builtins::CFunctionId id)
00505 : address_(Builtins::c_function_address(id)) {}
00506
00507
00508 ExternalReference::ExternalReference(Builtins::Name name)
00509 : address_(Builtins::builtin_address(name)) {}
00510
00511
00512 ExternalReference::ExternalReference(Runtime::FunctionId id)
00513 : address_(Runtime::FunctionForId(id)->entry) {}
00514
00515
00516 ExternalReference::ExternalReference(Runtime::Function* f)
00517 : address_(f->entry) {}
00518
00519
00520 ExternalReference::ExternalReference(const IC_Utility& ic_utility)
00521 : address_(ic_utility.address()) {}
00522
00523
00524 ExternalReference::ExternalReference(const Debug_Address& debug_address)
00525 : address_(debug_address.address()) {}
00526
00527
00528 ExternalReference::ExternalReference(StatsCounter* counter)
00529 : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
00530
00531
00532 ExternalReference::ExternalReference(Top::AddressId id)
00533 : address_(Top::get_address_from_id(id)) {}
00534
00535
00536 ExternalReference::ExternalReference(const SCTableReference& table_ref)
00537 : address_(table_ref.address()) {}
00538
00539
00540 ExternalReference ExternalReference::builtin_passed_function() {
00541 return ExternalReference(&Builtins::builtin_passed_function);
00542 }
00543
00544 ExternalReference ExternalReference::the_hole_value_location() {
00545 return ExternalReference(Factory::the_hole_value().location());
00546 }
00547
00548
00549 ExternalReference ExternalReference::address_of_stack_guard_limit() {
00550 return ExternalReference(StackGuard::address_of_jslimit());
00551 }
00552
00553
00554 ExternalReference ExternalReference::debug_break() {
00555 return ExternalReference(FUNCTION_ADDR(Debug::Break));
00556 }
00557
00558
00559 ExternalReference ExternalReference::new_space_start() {
00560 return ExternalReference(Heap::NewSpaceStart());
00561 }
00562
00563 ExternalReference ExternalReference::new_space_allocation_top_address() {
00564 return ExternalReference(Heap::NewSpaceAllocationTopAddress());
00565 }
00566
00567 ExternalReference ExternalReference::heap_always_allocate_scope_depth() {
00568 return ExternalReference(Heap::always_allocate_scope_depth_address());
00569 }
00570
00571 ExternalReference ExternalReference::new_space_allocation_limit_address() {
00572 return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
00573 }
00574
00575 ExternalReference ExternalReference::debug_step_in_fp_address() {
00576 return ExternalReference(Debug::step_in_fp_addr());
00577 }
00578
00579 } }