Remove more things

(stripped) dart_product before: 5307888
(stripped) dart_product after: 5275088

Reduction in size: 32800 bytes.

Removed entirely:

- debuginfo*
- elfgen*
- gdbjit*
- TraceBuffer
- vtune support

Removed in product:

- Compiler stats
- Code observers

R=asiva@google.com

Review URL: https://codereview.chromium.org/1711163002 .
This commit is contained in:
John McCutchan
2016-02-22 08:53:11 -08:00
parent b33be7dce0
commit fda3a9bc2b
34 changed files with 156 additions and 1795 deletions
-1
View File
@@ -5,7 +5,6 @@
#include "vm/bootstrap_natives.h"
#include "vm/object.h"
#include "vm/report.h"
namespace dart {
-1
View File
@@ -10,7 +10,6 @@
#include "vm/heap.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/report.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
+111 -102
View File
@@ -26,6 +26,73 @@ Benchmark* Benchmark::first_ = NULL;
Benchmark* Benchmark::tail_ = NULL;
const char* Benchmark::executable_ = NULL;
//
// Measure compile of all dart2js(compiler) functions.
//
static char* ComputeDart2JSPath(const char* arg) {
char buffer[2048];
char* dart2js_path = strdup(File::GetCanonicalPath(arg));
const char* compiler_path =
"%s%spkg%scompiler%slib%scompiler.dart";
const char* path_separator = File::PathSeparator();
ASSERT(path_separator != NULL && strlen(path_separator) == 1);
char* ptr = strrchr(dart2js_path, *path_separator);
while (ptr != NULL) {
*ptr = '\0';
OS::SNPrint(buffer, 2048, compiler_path,
dart2js_path,
path_separator,
path_separator,
path_separator,
path_separator,
path_separator);
if (File::Exists(buffer)) {
break;
}
ptr = strrchr(dart2js_path, *path_separator);
}
if (ptr == NULL) {
free(dart2js_path);
dart2js_path = NULL;
}
return dart2js_path;
}
static void func(Dart_NativeArguments args) {
}
static Dart_NativeFunction NativeResolver(Dart_Handle name,
int arg_count,
bool* auto_setup_scope) {
ASSERT(auto_setup_scope != NULL);
*auto_setup_scope = false;
return &func;
}
static void SetupDart2JSPackagePath() {
bool worked = bin::DartUtils::SetOriginalWorkingDirectory();
EXPECT(worked);
Dart_Handle result = bin::DartUtils::PrepareForScriptLoading(false, false);
DART_CHECK_VALID(result);
// Setup package root.
char buffer[2048];
char* executable_path =
strdup(File::GetCanonicalPath(Benchmark::Executable()));
const char* packages_path = "%s%s..%spackages";
const char* path_separator = File::PathSeparator();
OS::SNPrint(buffer, 2048, packages_path,
executable_path, path_separator, path_separator);
result = bin::DartUtils::SetupPackageRoot(buffer, NULL);
DART_CHECK_VALID(result);
}
void Benchmark::RunAll(const char* executable) {
SetExecutable(executable);
Benchmark* benchmark = first_;
@@ -66,6 +133,9 @@ BENCHMARK(CorelibCompileAll) {
}
#ifndef PRODUCT
BENCHMARK(CorelibCompilerStats) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
@@ -86,6 +156,47 @@ BENCHMARK(CorelibCompilerStats) {
}
BENCHMARK(Dart2JSCompilerStats) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
SetupDart2JSPackagePath();
char* dart_root = ComputeDart2JSPath(Benchmark::Executable());
char* script = NULL;
if (dart_root != NULL) {
HANDLESCOPE(thread);
script = OS::SCreate(NULL,
"import '%s/pkg/compiler/lib/compiler.dart';", dart_root);
Dart_Handle lib = TestCase::LoadTestScript(
script,
reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
EXPECT_VALID(lib);
} else {
Dart_Handle lib = TestCase::LoadTestScript(
"import 'pkg/compiler/lib/compiler.dart';",
reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
EXPECT_VALID(lib);
}
CompilerStats* stats = thread->isolate()->compiler_stats();
ASSERT(stats != NULL);
stats->EnableBenchmark();
Timer timer(true, "Compile all of dart2js benchmark");
timer.Start();
const bool old_flag = FLAG_background_compilation;
FLAG_background_compilation = false;
Dart_Handle result = Dart_CompileAll();
FLAG_background_compilation = old_flag;
EXPECT_VALID(result);
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
benchmark->set_score(elapsed_time);
free(dart_root);
free(script);
}
#endif // !PRODUCT
//
// Measure creation of core isolate from a snapshot.
//
@@ -254,70 +365,6 @@ BENCHMARK(DartStringAccess) {
}
//
// Measure compile of all dart2js(compiler) functions.
//
static char* ComputeDart2JSPath(const char* arg) {
char buffer[2048];
char* dart2js_path = strdup(File::GetCanonicalPath(arg));
const char* compiler_path =
"%s%spkg%scompiler%slib%scompiler.dart";
const char* path_separator = File::PathSeparator();
ASSERT(path_separator != NULL && strlen(path_separator) == 1);
char* ptr = strrchr(dart2js_path, *path_separator);
while (ptr != NULL) {
*ptr = '\0';
OS::SNPrint(buffer, 2048, compiler_path,
dart2js_path,
path_separator,
path_separator,
path_separator,
path_separator,
path_separator);
if (File::Exists(buffer)) {
break;
}
ptr = strrchr(dart2js_path, *path_separator);
}
if (ptr == NULL) {
free(dart2js_path);
dart2js_path = NULL;
}
return dart2js_path;
}
static void func(Dart_NativeArguments args) {
}
static Dart_NativeFunction NativeResolver(Dart_Handle name,
int arg_count,
bool* auto_setup_scope) {
ASSERT(auto_setup_scope != NULL);
*auto_setup_scope = false;
return &func;
}
static void SetupDart2JSPackagePath() {
bool worked = bin::DartUtils::SetOriginalWorkingDirectory();
EXPECT(worked);
Dart_Handle result = bin::DartUtils::PrepareForScriptLoading(false, false);
DART_CHECK_VALID(result);
// Setup package root.
char buffer[2048];
char* executable_path =
strdup(File::GetCanonicalPath(Benchmark::Executable()));
const char* packages_path = "%s%s..%spackages";
const char* path_separator = File::PathSeparator();
OS::SNPrint(buffer, 2048, packages_path,
executable_path, path_separator, path_separator);
result = bin::DartUtils::SetupPackageRoot(buffer, NULL);
DART_CHECK_VALID(result);
}
BENCHMARK(Dart2JSCompileAll) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
@@ -353,44 +400,6 @@ BENCHMARK(Dart2JSCompileAll) {
}
BENCHMARK(Dart2JSCompilerStats) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
SetupDart2JSPackagePath();
char* dart_root = ComputeDart2JSPath(Benchmark::Executable());
char* script = NULL;
if (dart_root != NULL) {
HANDLESCOPE(thread);
script = OS::SCreate(NULL,
"import '%s/pkg/compiler/lib/compiler.dart';", dart_root);
Dart_Handle lib = TestCase::LoadTestScript(
script,
reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
EXPECT_VALID(lib);
} else {
Dart_Handle lib = TestCase::LoadTestScript(
"import 'pkg/compiler/lib/compiler.dart';",
reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
EXPECT_VALID(lib);
}
CompilerStats* stats = thread->isolate()->compiler_stats();
ASSERT(stats != NULL);
stats->EnableBenchmark();
Timer timer(true, "Compile all of dart2js benchmark");
timer.Start();
const bool old_flag = FLAG_background_compilation;
FLAG_background_compilation = false;
Dart_Handle result = Dart_CompileAll();
FLAG_background_compilation = old_flag;
EXPECT_VALID(result);
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
benchmark->set_score(elapsed_time);
free(dart_root);
free(script);
}
//
// Measure frame lookup during stack traversal.
//
-1
View File
@@ -11,7 +11,6 @@
#include "vm/longjump.h"
#include "vm/log.h"
#include "vm/object_store.h"
#include "vm/report.h"
#include "vm/symbols.h"
namespace dart {
-1
View File
@@ -18,7 +18,6 @@
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/parser.h"
#include "vm/report.h"
#include "vm/resolver.h"
#include "vm/runtime_entry.h"
#include "vm/stack_frame.h"
+4
View File
@@ -10,6 +10,8 @@
namespace dart {
#ifndef PRODUCT
Mutex* CodeObservers::mutex_ = NULL;
intptr_t CodeObservers::observers_length_ = 0;
CodeObserver** CodeObservers::observers_ = NULL;
@@ -66,4 +68,6 @@ void CodeObservers::InitOnce() {
}
#endif // !PRODUCT
} // namespace dart
+3
View File
@@ -10,6 +10,8 @@
namespace dart {
#ifndef PRODUCT
class Mutex;
// Object observing code creation events. Used by external profilers and
@@ -65,6 +67,7 @@ class CodeObservers : public AllStatic {
static CodeObserver** observers_;
};
#endif // !PRODUCT
} // namespace dart
+4
View File
@@ -89,6 +89,8 @@ CompilerStats::CompilerStats(Isolate* isolate)
}
#ifndef PRODUCT
// This function is used as a callback in the log object to which the
// compiler stats are printed. It will be called only once, to print
// the accumulated text when all of the compiler stats values are
@@ -286,4 +288,6 @@ char* CompilerStats::PrintToZone() {
return stats_text;
}
#endif // !PRODUCT
} // namespace dart
+6 -4
View File
@@ -72,20 +72,22 @@ class CompilerStats {
};
#define INC_STAT(thread, counter, incr) \
if (FLAG_compiler_stats) { \
if (FLAG_support_compiler_stats && FLAG_compiler_stats) { \
MutexLocker ml((thread)->isolate()->mutex()); \
(thread)->isolate()->compiler_stats()->counter += (incr); \
}
#define STAT_VALUE(thread, counter) \
((FLAG_compiler_stats != false) ? \
((FLAG_support_compiler_stats && FLAG_compiler_stats) ? \
(thread)->isolate()->compiler_stats()->counter : 0)
#define CSTAT_TIMER_SCOPE(thr, t) \
TimerScope timer(FLAG_compiler_stats, \
FLAG_compiler_stats ? &((thr)->isolate()->compiler_stats()->t) : NULL, \
TimerScope timer(FLAG_support_compiler_stats && FLAG_compiler_stats, \
(FLAG_support_compiler_stats && FLAG_compiler_stats) ? \
&((thr)->isolate()->compiler_stats()->t) : NULL, \
thr);
} // namespace dart
#endif // VM_COMPILER_STATS_H_
+2 -2
View File
@@ -105,7 +105,7 @@ const char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot,
PortMap::InitOnce();
FreeListElement::InitOnce();
Api::InitOnce();
CodeObservers::InitOnce();
NOT_IN_PRODUCT(CodeObservers::InitOnce());
if (FLAG_profiler) {
ThreadInterrupter::InitOnce();
Profiler::InitOnce();
@@ -363,7 +363,7 @@ const char* Dart::Cleanup() {
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting code observers\n",
timestamp());
}
CodeObservers::DeleteAll();
NOT_IN_PRODUCT(CodeObservers::DeleteAll());
if (FLAG_support_timeline) {
if (FLAG_trace_shutdown) {
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down timeline\n",
-1
View File
@@ -16,7 +16,6 @@
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/debuginfo.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
-102
View File
@@ -1,102 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_DEBUGINFO_H_
#define VM_DEBUGINFO_H_
#include "platform/assert.h"
#include "platform/utils.h"
#include "vm/globals.h"
namespace dart {
// DebugInfo is used to generate minimal debug information containing code,
// symbols, and line numbers for generated code in the dart VM. This information
// can be used in two ways:
// - for debugging using a debugger
// - for generating information to be read by pprof to analyze Dart programs.
class DebugInfo {
public:
// A basic ByteBuffer which is growable and uses malloc/free.
class ByteBuffer {
public:
ByteBuffer() : size_(0), capacity_(0), data_(NULL) { }
~ByteBuffer() {
free(data_);
size_ = 0;
capacity_ = 0;
data_ = NULL;
}
uint8_t at(int index) const {
ASSERT(0 <= index);
ASSERT(index < size_);
ASSERT(size_ <= capacity_);
return data_[index];
}
uint8_t* data() const { return data_; }
void set_data(uint8_t* value) { data_ = value; }
int size() const { return size_; }
// Append an element.
void Add(const uint8_t value) {
Resize(size() + 1);
data_[size() - 1] = value;
}
private:
void Resize(int new_size) {
if (new_size > capacity_) {
int new_capacity = Utils::RoundUpToPowerOfTwo(new_size);
uint8_t* new_data =
reinterpret_cast<uint8_t*>(realloc(data_, new_capacity));
ASSERT(new_data != NULL);
data_ = new_data;
capacity_ = new_capacity;
}
size_ = new_size;
}
int size_;
int capacity_;
uint8_t* data_;
// Disallow assignment
DISALLOW_COPY_AND_ASSIGN(ByteBuffer);
};
~DebugInfo();
// Add the code starting at pc.
void AddCode(uword pc, intptr_t size);
// Add symbol information for a region (includes the start and end symbol),
// does not add the actual code.
void AddCodeRegion(const char* name, uword pc, intptr_t size);
// Write out all the debug information info the memory region.
bool WriteToMemory(ByteBuffer* region);
// Create a new debug information generator.
static DebugInfo* NewGenerator();
// Register this generated section with debuggger using the JIT interface.
static void RegisterSection(const char* name,
uword entry_point,
intptr_t size);
// Unregister all generated section from debuggger.
static void UnregisterAllSections();
private:
void* handle_;
DebugInfo();
DISALLOW_COPY_AND_ASSIGN(DebugInfo);
};
} // namespace dart
#endif // VM_DEBUGINFO_H_
-77
View File
@@ -1,77 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_ANDROID)
#include "vm/debuginfo.h"
#include "vm/elfgen.h"
#include "vm/gdbjit_android.h"
namespace dart {
DebugInfo::DebugInfo() {
handle_ = reinterpret_cast<void*>(new ElfGen());
ASSERT(handle_ != NULL);
}
DebugInfo::~DebugInfo() {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
delete elf_gen;
}
void DebugInfo::AddCode(uword pc, intptr_t size) {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
elf_gen->AddCode(pc, size);
}
void DebugInfo::AddCodeRegion(const char* name, uword pc, intptr_t size) {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
elf_gen->AddCodeRegion(name, pc, size);
}
bool DebugInfo::WriteToMemory(ByteBuffer* region) {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
return elf_gen->WriteToMemory(region);
}
DebugInfo* DebugInfo::NewGenerator() {
return new DebugInfo();
}
void DebugInfo::RegisterSection(const char* name,
uword entry_point,
intptr_t size) {
ElfGen* elf_section = new ElfGen();
ASSERT(elf_section != NULL);
elf_section->AddCode(entry_point, size);
elf_section->AddCodeRegion(name, entry_point, size);
ByteBuffer* dynamic_region = new ByteBuffer();
ASSERT(dynamic_region != NULL);
elf_section->WriteToMemory(dynamic_region);
::addDynamicSection(reinterpret_cast<const char*>(dynamic_region->data()),
dynamic_region->size());
dynamic_region->set_data(NULL);
delete dynamic_region;
delete elf_section;
}
void DebugInfo::UnregisterAllSections() {
::deleteDynamicSections();
}
} // namespace dart
#endif // defined(TARGET_OS_ANDROID)
-77
View File
@@ -1,77 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_LINUX)
#include "vm/debuginfo.h"
#include "vm/elfgen.h"
#include "vm/gdbjit_linux.h"
namespace dart {
DebugInfo::DebugInfo() {
handle_ = reinterpret_cast<void*>(new ElfGen());
ASSERT(handle_ != NULL);
}
DebugInfo::~DebugInfo() {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
delete elf_gen;
}
void DebugInfo::AddCode(uword pc, intptr_t size) {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
elf_gen->AddCode(pc, size);
}
void DebugInfo::AddCodeRegion(const char* name, uword pc, intptr_t size) {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
elf_gen->AddCodeRegion(name, pc, size);
}
bool DebugInfo::WriteToMemory(ByteBuffer* region) {
ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_);
return elf_gen->WriteToMemory(region);
}
DebugInfo* DebugInfo::NewGenerator() {
return new DebugInfo();
}
void DebugInfo::RegisterSection(const char* name,
uword entry_point,
intptr_t size) {
ElfGen* elf_section = new ElfGen();
ASSERT(elf_section != NULL);
elf_section->AddCode(entry_point, size);
elf_section->AddCodeRegion(name, entry_point, size);
ByteBuffer* dynamic_region = new ByteBuffer();
ASSERT(dynamic_region != NULL);
elf_section->WriteToMemory(dynamic_region);
::addDynamicSection(reinterpret_cast<const char*>(dynamic_region->data()),
dynamic_region->size());
dynamic_region->set_data(NULL);
delete dynamic_region;
delete elf_section;
}
void DebugInfo::UnregisterAllSections() {
::deleteDynamicSections();
}
} // namespace dart
#endif // defined(TARGET_OS_LINUX)
-509
View File
@@ -1,509 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_ELFGEN_H_
#define VM_ELFGEN_H_
#include "vm/lockers.h"
#include "vm/os_thread.h"
namespace dart {
// -----------------------------------------------------------------------------
// Implementation of ElfGen
//
// Specification documents:
// http://refspecs.freestandards.org
//
// ELF generic ABI:
// http://refspecs.freestandards.org/elf/gabi4+/contents.html
// ELF processor-specific supplement for X86_64:
// http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf
// DWARF 2.0:
// http://refspecs.freestandards.org/dwarf/dwarf-2.0.0.pdf
// Forward declarations.
class File;
// ElfGen is used to generate minimal ELF information containing code, symbols,
// and line numbers for generated code in the dart VM. This information is
// used in two ways:
// - it is used to generate in-memory ELF information which is then
// registered with gdb using the JIT interface.
// - it is also used to generate a file with the ELF information. This file
// is not executed, but read by pprof to analyze Dart programs.
class ElfGen {
public:
ElfGen();
~ElfGen();
// Add the code starting at pc.
void AddCode(uword pc, intptr_t size);
// Add symbol information for a region (includes the start and end symbol),
// does not add the actual code.
void AddCodeRegion(const char* name, uword pc, intptr_t size);
// Add specified symbol information, does not add the actual code.
int AddFunction(const char* name, uword pc, intptr_t size);
// Write out all the Elf information using the specified handle.
bool WriteToFile(File* handle);
bool WriteToMemory(DebugInfo::ByteBuffer* region);
// Register this generated section with GDB using the JIT interface.
static void RegisterSectionWithGDB(const char* name,
uword entry_point,
intptr_t size);
// Unregister all generated section from GDB.
static void UnregisterAllSectionsWithGDB();
private:
// ELF helpers
typedef int (*OutputWriter)(void* handle,
const DebugInfo::ByteBuffer& section);
typedef void (*OutputPadder)(void* handle, int padding_size);
int AddString(DebugInfo::ByteBuffer* buf, const char* str);
int AddSectionName(const char* str);
int AddName(const char* str);
void AddELFHeader(int shoff);
void AddSectionHeader(int section, int offset);
int PadSection(DebugInfo::ByteBuffer* section, int offset, int alignment);
bool WriteOutput(void* handle, OutputWriter writer, OutputPadder padder);
uword text_vma_; // text section vma
intptr_t text_size_; // text section size
int text_padding_; // padding preceding text section
static const int kNumSections = 5; // we generate 5 sections
int section_name_[kNumSections]; // array of section name indices
DebugInfo::ByteBuffer section_buf_[kNumSections]; // array of section buffers
DebugInfo::ByteBuffer header_; // ELF header buffer
DebugInfo::ByteBuffer sheaders_; // section header table buffer
DebugInfo::ByteBuffer lineprog_; // line statement program, part of
// '.debug_line' section
// current state of the DWARF line info generator
uintptr_t cur_addr_; // current pc
int map_offset_;
uword map_begin_;
uword map_end_;
Mutex lock_;
};
enum {
// Various constant sizes for ELF files.
kAddrSize = sizeof(uword),
kPageSize = 4*1024, // Memory mapping page size.
kTextAlign = 16,
kELFHeaderSize = 40 + 3*kAddrSize,
kProgramHeaderEntrySize = 8 + 6*kAddrSize,
kSectionHeaderEntrySize = 16 + 6*kAddrSize,
kSymbolSize = 8 + 2*kAddrSize,
// Our own layout of sections.
kUndef = 0, // Undefined section.
kText, // Text section.
kShStrtab, // Section header string table.
kStrtab, // String table.
kSymtab, // Symbol table.
kNumSections, // Num of section header entries in section header table.
// Various ELF constants.
kELFCLASS32 = 1,
kELFCLASS64 = 2,
kELFDATA2LSB = 1,
kELFDATA2MSB = 2,
kEM_386 = 3,
kEM_MIPS = 8,
kEM_ARM = 40,
kEM_X86_64 = 62,
kEV_CURRENT = 1,
kET_EXEC = 2, // not used
kET_DYN = 3,
kSHT_PROGBITS = 1,
kSHT_SYMTAB = 2,
kSHT_STRTAB = 3,
kSHF_WRITE = 1, // not used
kSHF_ALLOC = 2,
kSHF_EXECINSTR = 4,
kSTB_LOCAL = 0,
kSTB_EXPORTED = 1,
kSTT_FUNC = 2,
};
// ELF and DWARF constants.
static const char* kEI_MAG0_MAG3 = "\177ELF";
static const uint8_t kSpecialOpcodeLengths[] = { 0, 1, 1, 1, 1, 0, 0, 0, 1 };
// Section attributes.
// The field names correspond to the field names of Elf32_Shdr and Elf64_Shdr.
static const struct {
// Section header index (only used to check correct section order).
int shndx;
const char* name; // sh_name will be the index of name inserted in shstrtab.
int sh_type;
int sh_flags;
int sh_link;
int sh_addralign;
int sh_entsize;
} section_attr[kNumSections + 1] = {
{ kUndef, "", 0, 0,
0, 0, 0 },
{ kText, ".text", kSHT_PROGBITS, kSHF_ALLOC|kSHF_EXECINSTR,
0, kTextAlign, 0 },
{ kShStrtab, ".shstrtab", kSHT_STRTAB, 0,
0, 1, 0 },
{ kStrtab, ".strtab", kSHT_STRTAB, 0,
0, 1, 0 },
{ kSymtab, ".symtab", kSHT_SYMTAB, 0,
kStrtab, kAddrSize, kSymbolSize },
// Sentinel to pad the last section
// for proper alignment of section header table.
{ 0, "", 0, 0,
0, kAddrSize, 0 }
};
// Convenience function aligning an integer.
static inline uintptr_t Align(uintptr_t x, intptr_t size) {
// size is a power of 2
ASSERT((size & (size-1)) == 0);
return (x + (size-1)) & ~(size-1);
}
// Convenience function writing a single byte to a ByteBuffer.
static inline void WriteByte(DebugInfo::ByteBuffer* buf, uint8_t byte) {
buf->Add(byte);
}
// Convenience function writing an unsigned native word to a ByteBuffer.
// The word is 32-bit wide in 32-bit mode and 64-bit wide in 64-bit mode.
static inline void WriteWord(DebugInfo::ByteBuffer* buf, uword word) {
uint8_t* p = reinterpret_cast<uint8_t*>(&word);
for (size_t i = 0; i < sizeof(word); i++) {
buf->Add(p[i]);
}
}
static inline void WriteInt(DebugInfo::ByteBuffer* buf, int word) {
uint8_t* p = reinterpret_cast<uint8_t*>(&word);
for (size_t i = 0; i < sizeof(word); i++) {
buf->Add(p[i]);
}
}
static inline void WriteShort(DebugInfo::ByteBuffer* buf, uint16_t word) {
uint8_t* p = reinterpret_cast<uint8_t*>(&word);
for (size_t i = 0; i < sizeof(word); i++) {
buf->Add(p[i]);
}
}
static inline void WriteString(DebugInfo::ByteBuffer* buf, const char* str) {
for (size_t i = 0; i < strlen(str); i++) {
buf->Add(static_cast<uint8_t>(str[i]));
}
}
static inline void Write(DebugInfo::ByteBuffer* buf,
const void* mem,
int length) {
const uint8_t* p = reinterpret_cast<const uint8_t*>(mem);
for (int i = 0; i < length; i++) {
buf->Add(p[i]);
}
}
// Write given section to file and return written size.
static int WriteSectionToFile(void* handle,
const DebugInfo::ByteBuffer& section) {
#if 0
File* fp = reinterpret_cast<File*>(handle);
int size = section.size();
fp->WriteFully(section.data(), size);
return size;
#else
return 0;
#endif
}
// Pad output file to specified padding size.
static void PadFile(void* handle, int padding_size) {
#if 0
File* fp = reinterpret_cast<File*>(handle);
for (int i = 0; i < padding_size; i++) {
fp->WriteFully("", 1);
}
#endif
}
// Write given section to specified memory region and return written size.
static int WriteSectionToMemory(void* handle,
const DebugInfo::ByteBuffer& section) {
DebugInfo::ByteBuffer* buffer =
reinterpret_cast<DebugInfo::ByteBuffer*>(handle);
int size = section.size();
for (int i = 0; i < size; i++) {
buffer->Add(static_cast<uint8_t>(section.data()[i]));
}
return size;
}
// Pad memory to specified padding size.
static void PadMemory(void* handle, int padding_size) {
DebugInfo::ByteBuffer* buffer =
reinterpret_cast<DebugInfo::ByteBuffer*>(handle);
for (int i = 0; i < padding_size; i++) {
buffer->Add(static_cast<uint8_t>(0));
}
}
// Constructor
ElfGen::ElfGen()
: text_vma_(0), text_size_(0), text_padding_(0), map_offset_(0), lock_() {
for (int i = 0; i < kNumSections; i++) {
ASSERT(section_attr[i].shndx == i); // Verify layout of sections.
section_name_[i] = AddSectionName(section_attr[i].name);
}
// Section header string table always starts with an empty string, which is
// the name of the kUndef section.
ASSERT((section_attr[0].name[0] == '\0') && (section_name_[0] == 0));
// String table always starts with an empty string.
AddName("");
ASSERT(section_buf_[kStrtab].size() == 1);
// Symbol at index 0 in symtab is always STN_UNDEF (all zero):
DebugInfo::ByteBuffer* symtab = &section_buf_[kSymtab];
while (symtab->size() < kSymbolSize) {
WriteInt(symtab, 0);
}
ASSERT(symtab->size() == kSymbolSize);
}
// Destructor
ElfGen::~ElfGen() {
}
void ElfGen::AddCode(uword pc, intptr_t size) {
MutexLocker ml(&lock_);
text_vma_ = pc;
text_size_ = size;
// We pad the text section in the file to align absolute code addresses with
// corresponding file offsets as if the code had been loaded by memory
// mapping.
if (text_vma_ % kPageSize < kELFHeaderSize) {
text_padding_ = text_vma_ % kPageSize + kPageSize - kELFHeaderSize;
} else {
text_padding_ = text_vma_ % kPageSize - kELFHeaderSize;
}
Write(&section_buf_[kText], reinterpret_cast<void*>(pc), size);
// map_offset is the file offset of the first mapped page.
map_offset_ = (kELFHeaderSize + text_padding_)/kPageSize*kPageSize;
map_begin_ = Align(text_vma_ - kPageSize + 1, kPageSize);
map_end_ = Align(text_vma_ + size, kPageSize);
}
void ElfGen::AddCodeRegion(const char* name, uword pc, intptr_t size) {
MutexLocker ml(&lock_);
AddFunction(name, pc, size);
char end_name[256];
OS::SNPrint(end_name, sizeof(end_name), "%s_end", name);
AddFunction(end_name, pc + size, 0);
}
int ElfGen::AddFunction(const char* name, uword pc, intptr_t size) {
ASSERT(text_vma_ != 0); // code must have been added
DebugInfo::ByteBuffer* symtab = &section_buf_[kSymtab];
const int beg = symtab->size();
WriteInt(symtab, AddName(name)); // st_name
#if defined(ARCH_IS_64_BIT)
WriteShort(symtab, (kSTB_LOCAL << 4) + kSTT_FUNC); // st_info + (st_other<<8)
WriteShort(symtab, kText); // st_shndx
#endif
WriteWord(symtab, pc); // st_value
WriteWord(symtab, size); // st_size
#if defined(ARCH_IS_32_BIT)
// st_info + (st_other<<8)
WriteShort(symtab, (kSTB_EXPORTED << 4) + kSTT_FUNC);
WriteShort(symtab, kText); // st_shndx
#endif
ASSERT(symtab->size() - beg == kSymbolSize);
return beg / kSymbolSize; // symbol index in symtab
}
bool ElfGen::WriteToFile(File* handle) {
return WriteOutput(handle, WriteSectionToFile, PadFile);
}
bool ElfGen::WriteToMemory(DebugInfo::ByteBuffer* region) {
return WriteOutput(region, WriteSectionToMemory, PadMemory);
}
int ElfGen::AddString(DebugInfo::ByteBuffer* buf, const char* str) {
const int str_index = buf->size();
WriteString(buf, str);
WriteByte(buf, 0); // terminating '\0'
return str_index;
}
int ElfGen::AddSectionName(const char* str) {
return AddString(&section_buf_[kShStrtab], str);
}
int ElfGen::AddName(const char* str) {
return AddString(&section_buf_[kStrtab], str);
}
void ElfGen::AddELFHeader(int shoff) {
ASSERT(text_vma_ != 0); // Code must have been added.
Write(&header_, kEI_MAG0_MAG3, 4); // EI_MAG0..EI_MAG3
#if defined(ARCH_IS_32_BIT)
WriteByte(&header_, kELFCLASS32); // EI_CLASS
#elif defined(ARCH_IS_64_BIT)
WriteByte(&header_, kELFCLASS64); // EI_CLASS
#else
#error Unknown architecture.
#endif
WriteByte(&header_, kELFDATA2LSB); // EI_DATA
WriteByte(&header_, kEV_CURRENT); // EI_VERSION
WriteByte(&header_, 0); // EI_PAD
WriteInt(&header_, 0); // EI_PAD
WriteInt(&header_, 0); // EI_PAD
WriteShort(&header_, kET_DYN); // e_type, fake a shared object.
#if defined(TARGET_ARCH_IA32)
WriteShort(&header_, kEM_386); // e_machine
#elif defined(TARGET_ARCH_X64)
WriteShort(&header_, kEM_X86_64); // e_machine
#elif defined(TARGET_ARCH_ARM)
WriteShort(&header_, kEM_ARM); // e_machine
#elif defined(TARGET_ARCH_ARM64)
// TODO(zra): Find the right ARM64 constant.
WriteShort(&header_, kEM_ARM); // e_machine
#elif defined(TARGET_ARCH_MIPS)
WriteShort(&header_, kEM_MIPS); // e_machine
#else
#error Unknown architecture.
#endif
WriteInt(&header_, kEV_CURRENT); // e_version
WriteWord(&header_, 0); // e_entry: none
WriteWord(&header_, 0); // e_phoff: no program header table.
WriteWord(&header_, shoff); // e_shoff: section header table offset.
WriteInt(&header_, 0); // e_flags: no flags.
WriteShort(&header_, kELFHeaderSize); // e_ehsize: header size.
WriteShort(&header_, kProgramHeaderEntrySize); // e_phentsize
WriteShort(&header_, 0); // e_phnum: no entries program header table.
WriteShort(&header_, kSectionHeaderEntrySize); // e_shentsize
// e_shnum: number of section header entries.
WriteShort(&header_, kNumSections);
WriteShort(&header_, kShStrtab); // e_shstrndx: index of shstrtab.
ASSERT(header_.size() == kELFHeaderSize);
}
void ElfGen::AddSectionHeader(int section, int offset) {
WriteInt(&sheaders_, section_name_[section]);
WriteInt(&sheaders_, section_attr[section].sh_type);
WriteWord(&sheaders_, section_attr[section].sh_flags);
// sh_addr: abs addr
WriteWord(&sheaders_, (section == kText) ? text_vma_ : 0);
WriteWord(&sheaders_, offset); // sh_offset: section file offset.
WriteWord(&sheaders_, section_buf_[section].size());
WriteInt(&sheaders_, section_attr[section].sh_link);
WriteInt(&sheaders_, 0);
WriteWord(&sheaders_, section_attr[section].sh_addralign);
WriteWord(&sheaders_, section_attr[section].sh_entsize);
ASSERT(sheaders_.size() == kSectionHeaderEntrySize * (section + 1));
}
// Pads the given section with zero bytes for the given aligment, assuming the
// section starts at given file offset; returns file offset after padded
// section.
int ElfGen::PadSection(DebugInfo::ByteBuffer* section,
int offset,
int alignment) {
offset += section->size();
int aligned_offset = Align(offset, alignment);
while (offset++ < aligned_offset) {
WriteByte(section, 0); // one byte padding.
}
return aligned_offset;
}
bool ElfGen::WriteOutput(void* handle,
OutputWriter writer,
OutputPadder padder) {
if (handle == NULL || writer == NULL || padder == NULL) {
return false;
}
// Align all sections before writing the ELF header in order to calculate the
// file offset of the section header table, which is needed in the ELF header.
// Pad each section as required by the aligment constraint of the immediately
// following section, except the ELF header section, which requires special
// padding (text_padding_) to align the text_ section.
int offset = kELFHeaderSize + text_padding_;
for (int i = kText; i < kNumSections; i++) {
offset = PadSection(&section_buf_[i],
offset,
section_attr[i+1].sh_addralign);
}
const int shoff = offset; // Section header table offset.
// Write elf header.
AddELFHeader(shoff);
offset = (*writer)(handle, header_);
// Pad file before writing text section in order to align vma with file
// offset.
(*padder)(handle, text_padding_);
offset += text_padding_;
ASSERT((text_vma_ - offset) % kPageSize == 0);
// Section header at index 0 in section header table is always SHN_UNDEF:
for (int i = 0; i < kNumSections; i++) {
AddSectionHeader(i, offset);
offset += (*writer)(handle, section_buf_[i]);
}
// Write section header table.
ASSERT(offset == shoff);
offset += (*writer)(handle, sheaders_);
ASSERT(offset == shoff + kNumSections * kSectionHeaderEntrySize);
return true;
}
} // namespace dart
#endif // VM_ELFGEN_H_
+2
View File
@@ -38,6 +38,8 @@ R(profiler, false, bool, true, \
"Enable the profiler.") \
R(support_ast_printer, false, bool, true, \
"Support the AST printer.") \
R(support_compiler_stats, false, bool, true, \
"Support compiler stats.") \
R(support_debugger, false, bool, true, \
"Support the debugger.") \
R(support_disassembler, false, bool, true, \
-1
View File
@@ -12,7 +12,6 @@
#include "vm/intermediate_language.h"
#include "vm/growable_array.h"
#include "vm/object_store.h"
#include "vm/report.h"
namespace dart {
-84
View File
@@ -1,84 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_ANDROID)
#include <stdint.h> // NOLINT
#include <stdio.h> // NOLINT
#include <stdlib.h> // NOLINT
#include "vm/gdbjit_android.h"
extern "C" {
typedef enum {
JIT_NOACTION = 0,
JIT_REGISTER_FN,
JIT_UNREGISTER_FN
} jit_actions_t;
struct jit_code_entry {
struct jit_code_entry* next_entry;
struct jit_code_entry* prev_entry;
const char* symfile_addr;
uint64_t symfile_size;
};
struct jit_descriptor {
uint32_t version;
/* This type should be jit_actions_t, but we use uint32_t
to be explicit about the bitwidth. */
uint32_t action_flag;
struct jit_code_entry* relevant_entry;
struct jit_code_entry* first_entry;
};
#ifndef GDB_JIT_SYMBOLS
/* GDB puts a breakpoint in this function. */
void __attribute__((noinline)) __jit_debug_register_code() { }
/* Make sure to specify the version statically, because the
debugger may check the version before we can set it. */
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
#endif
static struct jit_code_entry* first_dynamic_region = NULL;
static struct jit_code_entry* last_dynamic_region = NULL;
void addDynamicSection(const char* symfile_addr, uint64_t symfile_size) {
jit_code_entry* new_entry = reinterpret_cast<jit_code_entry*>(
malloc(sizeof(jit_code_entry)));
if (new_entry != NULL) {
new_entry->symfile_addr = symfile_addr;
new_entry->symfile_size = symfile_size;
new_entry->next_entry = NULL;
new_entry->prev_entry = last_dynamic_region;
if (first_dynamic_region == NULL) {
first_dynamic_region = new_entry;
} else {
last_dynamic_region->next_entry = new_entry;
}
last_dynamic_region = new_entry;
}
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
__jit_debug_descriptor.relevant_entry = new_entry;
__jit_debug_descriptor.first_entry = first_dynamic_region;
__jit_debug_register_code();
}
void deleteDynamicSections() {
struct jit_code_entry* iterator = last_dynamic_region;
while (iterator != NULL) {
__jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
__jit_debug_descriptor.relevant_entry = iterator;
__jit_debug_descriptor.first_entry = first_dynamic_region;
__jit_debug_register_code();
iterator = iterator->prev_entry;
}
first_dynamic_region = NULL;
last_dynamic_region = NULL;
}
};
#endif // defined(TARGET_OS_ANDROID)
-15
View File
@@ -1,15 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_GDBJIT_ANDROID_H_
#define VM_GDBJIT_ANDROID_H_
#include <stdint.h>
extern "C" {
void addDynamicSection(const char* symfile_addr, uint64_t symfile_size);
void deleteDynamicSections();
};
#endif // VM_GDBJIT_ANDROID_H_
-84
View File
@@ -1,84 +0,0 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_LINUX)
#include <stdint.h> // NOLINT
#include <stdio.h> // NOLINT
#include <stdlib.h> // NOLINT
#include "vm/gdbjit_linux.h"
extern "C" {
typedef enum {
JIT_NOACTION = 0,
JIT_REGISTER_FN,
JIT_UNREGISTER_FN
} jit_actions_t;
struct jit_code_entry {
struct jit_code_entry* next_entry;
struct jit_code_entry* prev_entry;
const char* symfile_addr;
uint64_t symfile_size;
};
struct jit_descriptor {
uint32_t version;
/* This type should be jit_actions_t, but we use uint32_t
to be explicit about the bitwidth. */
uint32_t action_flag;
struct jit_code_entry* relevant_entry;
struct jit_code_entry* first_entry;
};
#ifndef GDB_JIT_SYMBOLS
/* GDB puts a breakpoint in this function. */
void __attribute__((noinline)) __jit_debug_register_code() { }
/* Make sure to specify the version statically, because the
debugger may check the version before we can set it. */
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
#endif
static struct jit_code_entry* first_dynamic_region = NULL;
static struct jit_code_entry* last_dynamic_region = NULL;
void addDynamicSection(const char* symfile_addr, uint64_t symfile_size) {
jit_code_entry* new_entry = reinterpret_cast<jit_code_entry*>(
malloc(sizeof(jit_code_entry)));
if (new_entry != NULL) {
new_entry->symfile_addr = symfile_addr;
new_entry->symfile_size = symfile_size;
new_entry->next_entry = NULL;
new_entry->prev_entry = last_dynamic_region;
if (first_dynamic_region == NULL) {
first_dynamic_region = new_entry;
} else {
last_dynamic_region->next_entry = new_entry;
}
last_dynamic_region = new_entry;
}
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
__jit_debug_descriptor.relevant_entry = new_entry;
__jit_debug_descriptor.first_entry = first_dynamic_region;
__jit_debug_register_code();
}
void deleteDynamicSections() {
struct jit_code_entry* iterator = last_dynamic_region;
while (iterator != NULL) {
__jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
__jit_debug_descriptor.relevant_entry = iterator;
__jit_debug_descriptor.first_entry = first_dynamic_region;
__jit_debug_register_code();
iterator = iterator->prev_entry;
}
first_dynamic_region = NULL;
last_dynamic_region = NULL;
}
};
#endif // defined(TARGET_OS_LINUX)
-15
View File
@@ -1,15 +0,0 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_GDBJIT_LINUX_H_
#define VM_GDBJIT_LINUX_H_
#include <stdint.h>
extern "C" {
void addDynamicSection(const char* symfile_addr, uint64_t symfile_size);
void deleteDynamicSections();
};
#endif // VM_GDBJIT_LINUX_H_
+7 -5
View File
@@ -18,6 +18,7 @@
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/deopt_instructions.h"
#include "vm/flags.h"
#include "vm/heap.h"
#include "vm/lockers.h"
#include "vm/log.h"
@@ -821,7 +822,6 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags)
last_allocationprofile_accumulator_reset_timestamp_(0),
last_allocationprofile_gc_timestamp_(0),
object_id_ring_(NULL),
trace_buffer_(NULL),
tag_table_(GrowableObjectArray::null()),
deoptimized_code_array_(GrowableObjectArray::null()),
background_compiler_(NULL),
@@ -962,9 +962,11 @@ Isolate* Isolate::Init(const char* name_prefix,
}
}
result->compiler_stats_ = new CompilerStats(result);
if (FLAG_compiler_benchmark) {
result->compiler_stats_->EnableBenchmark();
if (FLAG_support_compiler_stats) {
result->compiler_stats_ = new CompilerStats(result);
if (FLAG_compiler_benchmark) {
result->compiler_stats_->EnableBenchmark();
}
}
if (FLAG_support_service) {
@@ -1776,7 +1778,7 @@ void Isolate::Shutdown() {
}
// Write compiler stats data if enabled.
if (FLAG_compiler_stats
if (FLAG_support_compiler_stats && FLAG_compiler_stats
&& !ServiceIsolate::IsServiceIsolateDescendant(this)
&& (this != Dart::vm_isolate())) {
OS::Print("%s", compiler_stats()->PrintToZone());
+1 -11
View File
@@ -19,7 +19,7 @@
#include "vm/os_thread.h"
#include "vm/timeline.h"
#include "vm/timer.h"
#include "vm/trace_buffer.h"
#include "vm/token_position.h"
namespace dart {
@@ -494,13 +494,6 @@ class Isolate : public BaseIsolate {
return object_id_ring_;
}
void set_trace_buffer(TraceBuffer* buffer) {
trace_buffer_ = buffer;
}
TraceBuffer* trace_buffer() {
return trace_buffer_;
}
DeoptContext* deopt_context() const { return deopt_context_; }
void set_deopt_context(DeoptContext* value) {
ASSERT(value == NULL || deopt_context_ == NULL);
@@ -809,9 +802,6 @@ class Isolate : public BaseIsolate {
// Ring buffer of objects assigned an id.
ObjectIdRing* object_id_ring_;
// Trace buffer support.
TraceBuffer* trace_buffer_;
VMTagCounters vm_tag_counters_;
RawGrowableObjectArray* tag_table_;
+5 -3
View File
@@ -31,7 +31,6 @@
#include "vm/parser.h"
#include "vm/precompiler.h"
#include "vm/profiler.h"
#include "vm/report.h"
#include "vm/reusable_handles.h"
#include "vm/runtime_entry.h"
#include "vm/scopes.h"
@@ -12848,11 +12847,13 @@ RawCode* Code::FinalizeCode(const char* name,
CPU::FlushICache(instrs.EntryPoint(), instrs.size());
code.set_compile_timestamp(OS::GetCurrentMonotonicMicros());
#ifndef PRODUCT
CodeObservers::NotifyAll(name,
instrs.EntryPoint(),
assembler->prologue_offset(),
instrs.size(),
optimized);
#endif
{
NoSafepointScope no_safepoint;
const ZoneGrowableArray<intptr_t>& pointer_offsets =
@@ -12909,13 +12910,14 @@ RawCode* Code::FinalizeCode(const Function& function,
bool optimized) {
// Calling ToLibNamePrefixedQualifiedCString is very expensive,
// try to avoid it.
#ifndef PRODUCT
if (CodeObservers::AreActive()) {
return FinalizeCode(function.ToLibNamePrefixedQualifiedCString(),
assembler,
optimized);
} else {
return FinalizeCode("", assembler, optimized);
}
#endif // !PRODUCT
return FinalizeCode("", assembler, optimized);
}
+5 -46
View File
@@ -21,9 +21,7 @@
#include "platform/utils.h"
#include "vm/code_observers.h"
#include "vm/dart.h"
#include "vm/debuginfo.h"
#include "vm/isolate.h"
#include "vm/vtune.h"
#include "vm/zone.h"
@@ -31,12 +29,11 @@ namespace dart {
// Android CodeObservers.
DEFINE_FLAG(bool, generate_gdb_symbols, false,
"Generate symbols of generated dart functions for debugging with GDB");
#ifndef PRODUCT
DEFINE_FLAG(bool, generate_perf_events_symbols, false,
"Generate events symbols for profiling with perf");
class PerfCodeObserver : public CodeObserver {
public:
PerfCodeObserver() : out_file_(NULL) {
@@ -83,41 +80,7 @@ class PerfCodeObserver : public CodeObserver {
DISALLOW_COPY_AND_ASSIGN(PerfCodeObserver);
};
class GdbCodeObserver : public CodeObserver {
public:
GdbCodeObserver() { }
virtual bool IsActive() const {
return FLAG_generate_gdb_symbols;
}
virtual void Notify(const char* name,
uword base,
uword prologue_offset,
uword size,
bool optimized) {
if (prologue_offset > 0) {
// In order to ensure that gdb sees the first instruction of a function
// as the prologue sequence we register two symbols for the cases when
// the prologue sequence is not the first instruction:
// <name>_entry is used for code preceding the prologue sequence.
// <name> for rest of the code (first instruction is prologue sequence).
char* pname = OS::SCreate(Thread::Current()->zone(),
"%s_%s", name, "entry");
DebugInfo::RegisterSection(pname, base, size);
DebugInfo::RegisterSection(name,
(base + prologue_offset),
(size - prologue_offset));
} else {
DebugInfo::RegisterSection(name, base, size);
}
}
private:
DISALLOW_COPY_AND_ASSIGN(GdbCodeObserver);
};
#endif // !PRODUCT
const char* OS::Name() {
return "android";
@@ -427,15 +390,11 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
void OS::RegisterCodeObservers() {
#ifndef PRODUCT
if (FLAG_generate_perf_events_symbols) {
CodeObservers::Register(new PerfCodeObserver);
}
if (FLAG_generate_gdb_symbols) {
CodeObservers::Register(new GdbCodeObserver);
}
#if defined(DART_VTUNE_SUPPORT)
CodeObservers::Register(new VTuneCodeObserver);
#endif
#endif // !PRODUCT
}
+6 -260
View File
@@ -22,26 +22,21 @@
#include "platform/utils.h"
#include "vm/code_observers.h"
#include "vm/dart.h"
#include "vm/debuginfo.h"
#include "vm/flags.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/os_thread.h"
#include "vm/vtune.h"
#include "vm/zone.h"
namespace dart {
// Linux CodeObservers.
#ifndef PRODUCT
DEFINE_FLAG(bool, generate_gdb_symbols, false,
"Generate symbols of generated dart functions for debugging with GDB");
DEFINE_FLAG(bool, generate_perf_events_symbols, false,
"Generate events symbols for profiling with perf");
DEFINE_FLAG(bool, generate_perf_jitdump, false,
"Writes jitdump data for profiling with perf annotate");
// Linux CodeObservers.
class PerfCodeObserver : public CodeObserver {
public:
PerfCodeObserver() : out_file_(NULL) {
@@ -92,249 +87,7 @@ class PerfCodeObserver : public CodeObserver {
};
class GdbCodeObserver : public CodeObserver {
public:
GdbCodeObserver() { }
virtual bool IsActive() const {
return FLAG_generate_gdb_symbols;
}
virtual void Notify(const char* name,
uword base,
uword prologue_offset,
uword size,
bool optimized) {
if (prologue_offset > 0) {
// In order to ensure that gdb sees the first instruction of a function
// as the prologue sequence we register two symbols for the cases when
// the prologue sequence is not the first instruction:
// <name>_entry is used for code preceding the prologue sequence.
// <name> for rest of the code (first instruction is prologue sequence).
char* pname = OS::SCreate(Thread::Current()->zone(),
"%s_%s", name, "entry");
DebugInfo::RegisterSection(pname, base, size);
DebugInfo::RegisterSection(name,
(base + prologue_offset),
(size - prologue_offset));
} else {
DebugInfo::RegisterSection(name, base, size);
}
}
private:
DISALLOW_COPY_AND_ASSIGN(GdbCodeObserver);
};
#define CLOCKFD 3
#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) // NOLINT
class JitdumpCodeObserver : public CodeObserver {
public:
JitdumpCodeObserver() {
ASSERT(FLAG_generate_perf_jitdump);
out_file_ = NULL;
clock_fd_ = -1;
clock_id_ = kInvalidClockId;
code_sequence_ = 0;
Dart_FileOpenCallback file_open = Isolate::file_open_callback();
Dart_FileWriteCallback file_write = Isolate::file_write_callback();
Dart_FileCloseCallback file_close = Isolate::file_close_callback();
if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
return;
}
// The Jitdump code observer writes all jitted code into the file
// 'perf.jitdump' in the current working directory. We open the file once
// on initialization and close it when the VM is going down.
{
// Open the file.
const char* filename = "perf.jitdump";
out_file_ = (*file_open)(filename, true);
ASSERT(out_file_ != NULL);
// Write the jit dump header.
WriteHeader();
}
// perf uses an internal clock and because our output is merged with data
// collected by perf our timestamps must be consistent. Using
// the posix-clock-module (/dev/trace_clock) as our time source ensures
// we are consistent with the perf timestamps.
clock_id_ = kInvalidClockId;
clock_fd_ = open("/dev/trace_clock", O_RDONLY);
if (clock_fd_ >= 0) {
clock_id_ = FD_TO_CLOCKID(clock_fd_);
}
}
~JitdumpCodeObserver() {
Dart_FileCloseCallback file_close = Isolate::file_close_callback();
if (file_close == NULL) {
return;
}
ASSERT(out_file_ != NULL);
(*file_close)(out_file_);
if (clock_fd_ >= 0) {
close(clock_fd_);
}
}
virtual bool IsActive() const {
return FLAG_generate_perf_jitdump && (out_file_ != NULL);
}
virtual void Notify(const char* name,
uword base,
uword prologue_offset,
uword size,
bool optimized) {
WriteCodeLoad(name, base, prologue_offset, size, optimized);
}
private:
static const uint32_t kJitHeaderMagic = 0x4A695444;
static const uint32_t kJitHeaderMagicSw = 0x4454694A;
static const uint32_t kJitHeaderVersion = 0x1;
static const uint32_t kElfMachIA32 = 3;
static const uint32_t kElfMachX64 = 62;
static const uint32_t kElfMachARM = 40;
// TODO(zra): Find the right ARM64 constant.
static const uint32_t kElfMachARM64 = 40;
static const uint32_t kElfMachMIPS = 10;
static const int kInvalidClockId = -1;
struct jitheader {
uint32_t magic; /* characters "jItD" */
uint32_t version; /* header version */
uint32_t total_size; /* total size of header */
uint32_t elf_mach; /* elf mach target */
uint32_t pad1; /* reserved */
uint32_t pid; /* JIT process id */
uint64_t timestamp; /* timestamp */
};
/* record prefix (mandatory in each record) */
struct jr_prefix {
uint32_t id;
uint32_t total_size;
uint64_t timestamp;
};
enum jit_record_type {
JIT_CODE_LOAD = 0,
/* JIT_CODE_MOVE = 1, */
/* JIT_CODE_DEBUG_INFO = 2, */
/* JIT_CODE_CLOSE = 3, */
JIT_CODE_MAX = 4,
};
struct jr_code_load {
struct jr_prefix prefix;
uint32_t pid;
uint32_t tid;
uint64_t vma;
uint64_t code_addr;
uint64_t code_size;
uint64_t code_index;
};
const char* GenerateCodeName(const char* name, bool optimized) {
const char* marker = optimized ? "*" : "";
return OS::SCreate(Thread::Current()->zone(), "%s%s", marker, name);
}
uint32_t GetElfMach() {
#if defined(TARGET_ARCH_IA32)
return kElfMachIA32;
#elif defined(TARGET_ARCH_X64)
return kElfMachX64;
#elif defined(TARGET_ARCH_ARM)
return kElfMachARM;
#elif defined(TARGET_ARCH_ARM64)
return kElfMachARM64;
#elif defined(TARGET_ARCH_MIPS)
return kElfMachMIPS;
#else
#error Unknown architecture.
#endif
}
pid_t gettid() {
// libc doesn't wrap the Linux-specific gettid system call.
// Note that this thread id is not the same as the posix thread id.
return syscall(SYS_gettid);
}
uint64_t GetKernelTimeNanos() {
if (clock_id_ != kInvalidClockId) {
struct timespec ts;
int r = clock_gettime(clock_id_, &ts);
ASSERT(r == 0);
uint64_t nanos = static_cast<uint64_t>(ts.tv_sec) *
static_cast<uint64_t>(kNanosecondsPerSecond);
nanos += static_cast<uint64_t>(ts.tv_nsec);
return nanos;
} else {
return OS::GetCurrentTimeMicros() * kNanosecondsPerMicrosecond;
}
}
void WriteHeader() {
Dart_FileWriteCallback file_write = Isolate::file_write_callback();
ASSERT(file_write != NULL);
ASSERT(out_file_ != NULL);
jitheader header;
header.magic = kJitHeaderMagic;
header.version = kJitHeaderVersion;
header.total_size = sizeof(jitheader);
header.pad1 = 0x0;
header.elf_mach = GetElfMach();
header.pid = getpid();
header.timestamp = GetKernelTimeNanos();
{
MutexLocker ml(CodeObservers::mutex());
(*file_write)(&header, sizeof(header), out_file_);
}
}
void WriteCodeLoad(const char* name, uword base, uword prologue_offset,
uword code_size, bool optimized) {
Dart_FileWriteCallback file_write = Isolate::file_write_callback();
ASSERT(file_write != NULL);
ASSERT(out_file_ != NULL);
const char* code_name = GenerateCodeName(name, optimized);
const intptr_t code_name_size = strlen(code_name) + 1;
uint8_t* code_pointer = reinterpret_cast<uint8_t*>(base);
jr_code_load code_load;
code_load.prefix.id = JIT_CODE_LOAD;
code_load.prefix.total_size =
sizeof(code_load) + code_name_size + code_size;
code_load.prefix.timestamp = GetKernelTimeNanos();
code_load.pid = getpid();
code_load.tid = gettid();
code_load.vma = 0x0; // Our addresses are absolute.
code_load.code_addr = base;
code_load.code_size = code_size;
{
MutexLocker ml(CodeObservers::mutex());
// Set this field under the index.
code_load.code_index = code_sequence_++;
// Write structures.
(*file_write)(&code_load, sizeof(code_load), out_file_);
(*file_write)(code_name, code_name_size, out_file_);
(*file_write)(code_pointer, code_size, out_file_);
}
}
void* out_file_;
int clock_fd_;
int clock_id_;
uint64_t code_sequence_;
DISALLOW_COPY_AND_ASSIGN(JitdumpCodeObserver);
};
#endif // !PRODUCT
const char* OS::Name() {
return "linux";
@@ -617,18 +370,11 @@ bool OS::StringToInt64(const char* str, int64_t* value) {
void OS::RegisterCodeObservers() {
#ifndef PRODUCT
if (FLAG_generate_perf_events_symbols) {
CodeObservers::Register(new PerfCodeObserver);
}
if (FLAG_generate_gdb_symbols) {
CodeObservers::Register(new GdbCodeObserver);
}
if (FLAG_generate_perf_jitdump) {
CodeObservers::Register(new JitdumpCodeObserver);
}
#if defined(DART_VTUNE_SUPPORT)
CodeObservers::Register(new VTuneCodeObserver);
#endif
#endif // !PRODUCT
}
-1
View File
@@ -28,7 +28,6 @@
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/regexp_assembler.h"
#include "vm/report.h"
#include "vm/resolver.h"
#include "vm/safepoint.h"
#include "vm/scanner.h"
-2
View File
@@ -12,8 +12,6 @@
namespace dart {
class JSONObject;
// Timer class allows timing of specific operations in the VM.
class Timer : public ValueObject {
public:
-136
View File
@@ -1,136 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/trace_buffer.h"
namespace dart {
TraceBuffer::TraceBuffer(Isolate* isolate, intptr_t capacity)
: isolate_(isolate), ring_capacity_(capacity) {
ring_cursor_ = 0;
ring_ = reinterpret_cast<TraceBufferEntry*>(
calloc(ring_capacity_, sizeof(TraceBufferEntry))); // NOLINT
}
TraceBuffer::~TraceBuffer() {
ASSERT(ring_ != NULL);
Clear();
free(ring_);
if (isolate_ != NULL) {
isolate_->set_trace_buffer(NULL);
isolate_ = NULL;
}
}
void TraceBuffer::Init(Isolate* isolate, intptr_t capacity) {
TraceBuffer* trace_buffer = new TraceBuffer(isolate, capacity);
isolate->set_trace_buffer(trace_buffer);
}
void TraceBuffer::Clear() {
for (intptr_t i = 0; i < ring_capacity_; i++) {
TraceBufferEntry& entry = ring_[i];
entry.micros = 0;
free(entry.message);
entry.message = NULL;
entry.message_is_escaped = false;
}
ring_cursor_ = 0;
}
void TraceBuffer::Fill(TraceBufferEntry* entry, int64_t micros,
char* msg, bool msg_is_escaped) {
if (entry->message != NULL) {
// Recycle TraceBufferEntry.
free(entry->message);
}
entry->message = msg;
entry->message_is_escaped = msg_is_escaped;
entry->micros = micros;
}
void TraceBuffer::AppendTrace(int64_t micros, char* msg, bool msg_is_escaped) {
const intptr_t index = ring_cursor_;
TraceBufferEntry* trace_entry = &ring_[index];
Fill(trace_entry, micros, msg, msg_is_escaped);
ring_cursor_ = RingIndex(ring_cursor_ + 1);
}
void TraceBuffer::Trace(int64_t micros, const char* msg, bool msg_is_escaped) {
ASSERT(msg != NULL);
char* message_copy = strdup(msg);
AppendTrace(micros, message_copy, msg_is_escaped);
}
void TraceBuffer::Trace(const char* msg, bool msg_is_escaped) {
Trace(OS::GetCurrentTimeMicros(), msg, msg_is_escaped);
}
void TraceBuffer::TraceF(const char* format, ...) {
const int64_t micros = OS::GetCurrentTimeMicros();
va_list args;
va_start(args, format);
const intptr_t len = OS::VSNPrint(NULL, 0, format, args);
va_end(args);
char* p = reinterpret_cast<char*>(malloc(len+1));
va_start(args, format);
const intptr_t len2 = OS::VSNPrint(p, len+1, format, args);
va_end(args);
ASSERT(len == len2);
AppendTrace(micros, p);
}
void TraceBuffer::PrintToJSONStream(JSONStream* stream) const {
JSONObject json_trace_buffer(stream);
json_trace_buffer.AddProperty("type", "TraceBuffer");
// TODO(johnmccutchan): Send cursor position in response.
JSONArray json_trace_buffer_array(&json_trace_buffer, "members");
// Scan forward until we find the first entry which isn't empty.
// TODO(johnmccutchan): Accept cursor start position as input.
intptr_t start = -1;
for (intptr_t i = 0; i < ring_capacity_; i++) {
intptr_t index = RingIndex(i + ring_cursor_);
if (!ring_[index].empty()) {
start = index;
break;
}
}
// No messages in trace buffer.
if (start == -1) {
return;
}
for (intptr_t i = 0; i < ring_capacity_; i++) {
intptr_t index = RingIndex(start + i);
const TraceBufferEntry& entry = ring_[index];
if (entry.empty()) {
// Empty entry, stop.
break;
}
JSONObject trace_entry(&json_trace_buffer_array);
trace_entry.AddProperty("type", "TraceBufferEntry");
double seconds = static_cast<double>(entry.micros) /
static_cast<double>(kMicrosecondsPerSecond);
trace_entry.AddProperty("time", seconds);
if (entry.message_is_escaped) {
trace_entry.AddPropertyNoEscape("message", entry.message);
} else {
trace_entry.AddProperty("message", entry.message);
}
}
}
} // namespace dart
-70
View File
@@ -1,70 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_TRACE_BUFFER_H_
#define VM_TRACE_BUFFER_H_
#include "platform/assert.h"
#include "platform/globals.h"
#include "vm/json_stream.h"
namespace dart {
class JSONStream;
class Script;
struct TraceBufferEntry {
int64_t micros;
char* message;
bool message_is_escaped;
bool empty() const {
return message == NULL;
}
};
class TraceBuffer {
public:
static const intptr_t kDefaultCapacity = 1024;
static void Init(Isolate* isolate, intptr_t capacity = kDefaultCapacity);
~TraceBuffer();
void Clear();
// Internally message is copied.
void Trace(int64_t micros, const char* msg, bool msg_is_escaped = false);
// Internally message is copied.
void Trace(const char* msg, bool msg_is_escaped = false);
void TraceF(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
void PrintToJSONStream(JSONStream* stream) const;
// Accessors for testing.
TraceBufferEntry* At(intptr_t i) const { return &ring_[RingIndex(i)]; }
intptr_t Length() const { return ring_cursor_; }
private:
TraceBuffer(Isolate* isolate, intptr_t capacity);
void Cleanup();
void Fill(TraceBufferEntry* entry, int64_t micros,
char* msg, bool msg_is_escaped = false);
void AppendTrace(int64_t micros, char* msg, bool msg_is_escaped = false);
Isolate* isolate_;
TraceBufferEntry* ring_;
const intptr_t ring_capacity_;
intptr_t ring_cursor_;
intptr_t RingIndex(intptr_t i) const {
return i % ring_capacity_;
}
DISALLOW_COPY_AND_ASSIGN(TraceBuffer);
};
} // namespace dart
#endif // VM_TRACE_BUFFER_H_
-110
View File
@@ -1,110 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/json_stream.h"
#include "vm/trace_buffer.h"
#include "vm/unit_test.h"
namespace dart {
#ifndef PRODUCT
TEST_CASE(TraceBufferEmpty) {
Isolate* isolate = Isolate::Current();
TraceBuffer::Init(isolate, 3);
TraceBuffer* trace_buffer = isolate->trace_buffer();
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_STREQ("{\"type\":\"TraceBuffer\",\"members\":[]}", js.ToCString());
}
delete trace_buffer;
}
TEST_CASE(TraceBufferClear) {
Isolate* isolate = Isolate::Current();
TraceBuffer::Init(isolate, 3);
TraceBuffer* trace_buffer = isolate->trace_buffer();
trace_buffer->Trace(kMicrosecondsPerSecond * 1, "abc");
trace_buffer->Clear();
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_STREQ("{\"type\":\"TraceBuffer\",\"members\":[]}", js.ToCString());
}
delete trace_buffer;
}
TEST_CASE(TraceBufferTrace) {
Isolate* isolate = Isolate::Current();
TraceBuffer::Init(isolate, 3);
TraceBuffer* trace_buffer = isolate->trace_buffer();
trace_buffer->Trace(kMicrosecondsPerSecond * 1, "abc");
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_STREQ("{\"type\":\"TraceBuffer\",\"members\":["
"{\"type\":\"TraceBufferEntry\",\"time\":1.000000,"
"\"message\":\"abc\"}]}", js.ToCString());
}
trace_buffer->Trace(kMicrosecondsPerSecond * 2, "def");
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_STREQ("{\"type\":\"TraceBuffer\",\"members\":["
"{\"type\":\"TraceBufferEntry\",\"time\":1.000000,"
"\"message\":\"abc\"},"
"{\"type\":\"TraceBufferEntry\",\"time\":2.000000,"
"\"message\":\"def\"}]}", js.ToCString());
}
trace_buffer->Trace(kMicrosecondsPerSecond * 3, "ghi");
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_STREQ("{\"type\":\"TraceBuffer\",\"members\":["
"{\"type\":\"TraceBufferEntry\",\"time\":1.000000,"
"\"message\":\"abc\"},"
"{\"type\":\"TraceBufferEntry\",\"time\":2.000000,"
"\"message\":\"def\"},"
"{\"type\":\"TraceBufferEntry\",\"time\":3.000000,"
"\"message\":\"ghi\"}]}", js.ToCString());
}
// This will overwrite the first Trace.
trace_buffer->Trace(kMicrosecondsPerSecond * 4, "jkl");
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_STREQ("{\"type\":\"TraceBuffer\",\"members\":["
"{\"type\":\"TraceBufferEntry\",\"time\":2.000000,"
"\"message\":\"def\"},"
"{\"type\":\"TraceBufferEntry\",\"time\":3.000000,"
"\"message\":\"ghi\"},"
"{\"type\":\"TraceBufferEntry\",\"time\":4.000000,"
"\"message\":\"jkl\"}]}", js.ToCString());
}
delete trace_buffer;
}
TEST_CASE(TraceBufferTraceF) {
Isolate* isolate = Isolate::Current();
TraceBuffer::Init(isolate, 3);
TraceBuffer* trace_buffer = isolate->trace_buffer();
trace_buffer->TraceF("foo %d %s", 99, "bar");
{
JSONStream js;
trace_buffer->PrintToJSONStream(&js);
EXPECT_SUBSTRING("foo 99 bar", js.ToCString());
}
delete trace_buffer;
}
#endif // !PRODUCT
} // namespace dart
-13
View File
@@ -144,9 +144,6 @@
'debugger_ia32.cc',
'debugger_mips.cc',
'debugger_x64.cc',
'debuginfo.h',
'debuginfo_android.cc',
'debuginfo_linux.cc',
'deferred_objects.cc',
'deferred_objects.h',
'deopt_instructions.cc',
@@ -162,7 +159,6 @@
'double_conversion.cc',
'double_conversion.h',
'double_internals.h',
'elfgen.h',
'exceptions.cc',
'exceptions.h',
'exceptions_test.cc',
@@ -201,10 +197,6 @@
'gc_marker.h',
'gc_sweeper.cc',
'gc_sweeper.h',
'gdbjit_android.cc',
'gdbjit_android.h',
'gdbjit_linux.cc',
'gdbjit_linux.h',
'globals.h',
'growable_array.h',
'growable_array_test.cc',
@@ -482,9 +474,6 @@
'token.h',
'token_position.cc',
'token_position.h',
'trace_buffer.cc',
'trace_buffer.h',
'trace_buffer_test.cc',
'unibrow.cc',
'unibrow.h',
'unibrow-inl.h',
@@ -508,8 +497,6 @@
'virtual_memory_test.cc',
'virtual_memory_win.cc',
'visitor.h',
'vtune.cc',
'vtune.h',
'weak_code.cc',
'weak_code.h',
'weak_table.cc',
-33
View File
@@ -1,33 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/vtune.h"
#include <jitprofiling.h>
#include "platform/assert.h"
namespace dart {
bool VTuneCodeObserver::IsActive() const {
return (iJIT_IsProfilingActive() == iJIT_SAMPLING_ON);
}
void VTuneCodeObserver::Notify(const char* name,
uword base,
uword prologue_offset,
uword size,
bool optimized) {
ASSERT(IsActive());
iJIT_Method_Load jmethod;
memset(&jmethod, 0, sizeof(jmethod));
jmethod.method_id = iJIT_GetNewMethodID();
jmethod.method_name = const_cast<char*>(name);
jmethod.method_load_address = reinterpret_cast<void*>(base);
jmethod.method_size = size;
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &jmethod);
}
} // namespace dart
-28
View File
@@ -1,28 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_VTUNE_H_
#define VM_VTUNE_H_
#include "vm/code_observers.h"
namespace dart {
#if defined(DART_VTUNE_SUPPORT)
class VTuneCodeObserver : public CodeObserver {
public:
virtual bool IsActive() const;
virtual void Notify(const char* name,
uword base,
uword prologue_offset,
uword size,
bool optimized);
};
#endif
} // namespace dart
#endif // VM_VTUNE_H_