Make static API getters inlineable again.

This relands r11376 with minor fixes for Windows where offsets are
slightly different from Linux for unaligned fields.

R=svenpanne@chromium.org
TEST=cctest/test-api/StaticGetters

Review URL: https://chromiumcodereview.appspot.com/10176004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11417 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e3be5951
...@@ -2561,6 +2561,11 @@ Handle<Primitive> V8EXPORT Null(); ...@@ -2561,6 +2561,11 @@ Handle<Primitive> V8EXPORT Null();
Handle<Boolean> V8EXPORT True(); Handle<Boolean> V8EXPORT True();
Handle<Boolean> V8EXPORT False(); Handle<Boolean> V8EXPORT False();
inline Handle<Primitive> Undefined(Isolate* isolate);
inline Handle<Primitive> Null(Isolate* isolate);
inline Handle<Boolean> True(Isolate* isolate);
inline Handle<Boolean> False(Isolate* isolate);
/** /**
* A set of constraints that specifies the limits of the runtime's memory use. * A set of constraints that specifies the limits of the runtime's memory use.
...@@ -3872,18 +3877,6 @@ const uintptr_t kEncodablePointerMask = ...@@ -3872,18 +3877,6 @@ const uintptr_t kEncodablePointerMask =
PlatformSmiTagging::kEncodablePointerMask; PlatformSmiTagging::kEncodablePointerMask;
const int kPointerToSmiShift = PlatformSmiTagging::kPointerToSmiShift; const int kPointerToSmiShift = PlatformSmiTagging::kPointerToSmiShift;
template <size_t ptr_size> struct InternalConstants;
// Internal constants for 32-bit systems.
template <> struct InternalConstants<4> {
static const int kStringResourceOffset = 3 * kApiPointerSize;
};
// Internal constants for 64-bit systems.
template <> struct InternalConstants<8> {
static const int kStringResourceOffset = 3 * kApiPointerSize;
};
/** /**
* This class exports constants and functionality from within v8 that * This class exports constants and functionality from within v8 that
* is necessary to implement inline functions in the v8 api. Don't * is necessary to implement inline functions in the v8 api. Don't
...@@ -3895,8 +3888,7 @@ class Internals { ...@@ -3895,8 +3888,7 @@ class Internals {
// the implementation of v8. // the implementation of v8.
static const int kHeapObjectMapOffset = 0; static const int kHeapObjectMapOffset = 0;
static const int kMapInstanceTypeOffset = 1 * kApiPointerSize + kApiIntSize; static const int kMapInstanceTypeOffset = 1 * kApiPointerSize + kApiIntSize;
static const int kStringResourceOffset = static const int kStringResourceOffset = 3 * kApiPointerSize;
InternalConstants<kApiPointerSize>::kStringResourceOffset;
static const int kOddballKindOffset = 3 * kApiPointerSize; static const int kOddballKindOffset = 3 * kApiPointerSize;
static const int kForeignAddressOffset = kApiPointerSize; static const int kForeignAddressOffset = kApiPointerSize;
...@@ -3904,6 +3896,14 @@ class Internals { ...@@ -3904,6 +3896,14 @@ class Internals {
static const int kFullStringRepresentationMask = 0x07; static const int kFullStringRepresentationMask = 0x07;
static const int kExternalTwoByteRepresentationTag = 0x02; static const int kExternalTwoByteRepresentationTag = 0x02;
static const int kIsolateStateOffset = 0;
static const int kIsolateEmbedderDataOffset = 1 * kApiPointerSize;
static const int kIsolateRootsOffset = 3 * kApiPointerSize;
static const int kUndefinedValueRootIndex = 5;
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
static const int kJSObjectType = 0xaa; static const int kJSObjectType = 0xaa;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x82; static const int kOddballType = 0x82;
...@@ -3956,6 +3956,16 @@ class Internals { ...@@ -3956,6 +3956,16 @@ class Internals {
return representation == kExternalTwoByteRepresentationTag; return representation == kExternalTwoByteRepresentationTag;
} }
static inline bool IsInitialized(v8::Isolate* isolate) {
uint8_t* addr = reinterpret_cast<uint8_t*>(isolate) + kIsolateStateOffset;
return *reinterpret_cast<int*>(addr) == 1;
}
static inline internal::Object** GetRoot(v8::Isolate* isolate, int index) {
uint8_t* addr = reinterpret_cast<uint8_t*>(isolate) + kIsolateRootsOffset;
return reinterpret_cast<internal::Object**>(addr + index * kApiPointerSize);
}
template <typename T> template <typename T>
static inline T ReadField(Object* ptr, int offset) { static inline T ReadField(Object* ptr, int offset) {
uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag; uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag;
...@@ -4378,6 +4388,42 @@ Local<Object> AccessorInfo::Holder() const { ...@@ -4378,6 +4388,42 @@ Local<Object> AccessorInfo::Holder() const {
} }
Handle<Primitive> Undefined(Isolate* isolate) {
typedef internal::Object* S;
typedef internal::Internals I;
if (!I::IsInitialized(isolate)) return Undefined();
S* slot = I::GetRoot(isolate, I::kUndefinedValueRootIndex);
return Handle<Primitive>(reinterpret_cast<Primitive*>(slot));
}
Handle<Primitive> Null(Isolate* isolate) {
typedef internal::Object* S;
typedef internal::Internals I;
if (!I::IsInitialized(isolate)) return Null();
S* slot = I::GetRoot(isolate, I::kNullValueRootIndex);
return Handle<Primitive>(reinterpret_cast<Primitive*>(slot));
}
Handle<Boolean> True(Isolate* isolate) {
typedef internal::Object* S;
typedef internal::Internals I;
if (!I::IsInitialized(isolate)) return True();
S* slot = I::GetRoot(isolate, I::kTrueValueRootIndex);
return Handle<Boolean>(reinterpret_cast<Boolean*>(slot));
}
Handle<Boolean> False(Isolate* isolate) {
typedef internal::Object* S;
typedef internal::Internals I;
if (!I::IsInitialized(isolate)) return False();
S* slot = I::GetRoot(isolate, I::kFalseValueRootIndex);
return Handle<Boolean>(reinterpret_cast<Boolean*>(slot));
}
/** /**
* \example shell.cc * \example shell.cc
* A simple shell that takes a list of expressions on the * A simple shell that takes a list of expressions on the
......
...@@ -1419,6 +1419,11 @@ class Heap { ...@@ -1419,6 +1419,11 @@ class Heap {
kRootListLength kRootListLength
}; };
STATIC_CHECK(kUndefinedValueRootIndex == Internals::kUndefinedValueRootIndex);
STATIC_CHECK(kNullValueRootIndex == Internals::kNullValueRootIndex);
STATIC_CHECK(kTrueValueRootIndex == Internals::kTrueValueRootIndex);
STATIC_CHECK(kFalseValueRootIndex == Internals::kFalseValueRootIndex);
MUST_USE_RESULT MaybeObject* NumberToString( MUST_USE_RESULT MaybeObject* NumberToString(
Object* number, bool check_number_string_cache = true); Object* number, bool check_number_string_cache = true);
MUST_USE_RESULT MaybeObject* Uint32ToString( MUST_USE_RESULT MaybeObject* Uint32ToString(
...@@ -1613,6 +1618,8 @@ class Heap { ...@@ -1613,6 +1618,8 @@ class Heap {
// more expedient to get at the isolate directly from within Heap methods. // more expedient to get at the isolate directly from within Heap methods.
Isolate* isolate_; Isolate* isolate_;
Object* roots_[kRootListLength];
intptr_t code_range_size_; intptr_t code_range_size_;
int reserved_semispace_size_; int reserved_semispace_size_;
int max_semispace_size_; int max_semispace_size_;
...@@ -1728,8 +1735,6 @@ class Heap { ...@@ -1728,8 +1735,6 @@ class Heap {
// last GC. // last GC.
int old_gen_exhausted_; int old_gen_exhausted_;
Object* roots_[kRootListLength];
Object* global_contexts_list_; Object* global_contexts_list_;
StoreBufferRebuilder store_buffer_rebuilder_; StoreBufferRebuilder store_buffer_rebuilder_;
......
...@@ -1430,6 +1430,7 @@ void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) { ...@@ -1430,6 +1430,7 @@ void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
Isolate::Isolate() Isolate::Isolate()
: state_(UNINITIALIZED), : state_(UNINITIALIZED),
embedder_data_(NULL),
entry_stack_(NULL), entry_stack_(NULL),
stack_trace_nesting_level_(0), stack_trace_nesting_level_(0),
incomplete_message_(NULL), incomplete_message_(NULL),
...@@ -1472,7 +1473,6 @@ Isolate::Isolate() ...@@ -1472,7 +1473,6 @@ Isolate::Isolate()
string_tracker_(NULL), string_tracker_(NULL),
regexp_stack_(NULL), regexp_stack_(NULL),
date_cache_(NULL), date_cache_(NULL),
embedder_data_(NULL),
context_exit_happened_(false) { context_exit_happened_(false) {
TRACE_ISOLATE(constructor); TRACE_ISOLATE(constructor);
...@@ -1857,6 +1857,13 @@ bool Isolate::Init(Deserializer* des) { ...@@ -1857,6 +1857,13 @@ bool Isolate::Init(Deserializer* des) {
LOG(this, LogCompiledFunctions()); LOG(this, LogCompiledFunctions());
} }
CHECK_EQ(OFFSET_OF(Isolate, state_),
static_cast<intptr_t>(Internals::kIsolateStateOffset));
CHECK_EQ(OFFSET_OF(Isolate, embedder_data_),
static_cast<intptr_t>(Internals::kIsolateEmbedderDataOffset));
CHECK_EQ(OFFSET_OF(Isolate, heap_.roots_),
static_cast<intptr_t>(Internals::kIsolateRootsOffset));
state_ = INITIALIZED; state_ = INITIALIZED;
time_millis_at_init_ = OS::TimeCurrentMillis(); time_millis_at_init_ = OS::TimeCurrentMillis();
return true; return true;
......
...@@ -422,7 +422,7 @@ class Isolate { ...@@ -422,7 +422,7 @@ class Isolate {
enum AddressId { enum AddressId {
#define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address, #define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM) FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
#undef C #undef DECLARE_ENUM
kIsolateAddressCount kIsolateAddressCount
}; };
...@@ -1038,6 +1038,18 @@ class Isolate { ...@@ -1038,6 +1038,18 @@ class Isolate {
friend struct GlobalState; friend struct GlobalState;
friend struct InitializeGlobalState; friend struct InitializeGlobalState;
enum State {
UNINITIALIZED, // Some components may not have been allocated.
INITIALIZED // All components are fully initialized.
};
// These fields are accessed through the API, offsets must be kept in sync
// with v8::internal::Internals (in include/v8.h) constants. This is also
// verified in Isolate::Init() using runtime checks.
State state_; // Will be padded to kApiPointerSize.
void* embedder_data_;
Heap heap_;
// The per-process lock should be acquired before the ThreadDataTable is // The per-process lock should be acquired before the ThreadDataTable is
// modified. // modified.
class ThreadDataTable { class ThreadDataTable {
...@@ -1095,14 +1107,6 @@ class Isolate { ...@@ -1095,14 +1107,6 @@ class Isolate {
static void SetIsolateThreadLocals(Isolate* isolate, static void SetIsolateThreadLocals(Isolate* isolate,
PerIsolateThreadData* data); PerIsolateThreadData* data);
enum State {
UNINITIALIZED, // Some components may not have been allocated.
INITIALIZED // All components are fully initialized.
};
State state_;
EntryStackItem* entry_stack_;
// Allocate and insert PerIsolateThreadData into the ThreadDataTable // Allocate and insert PerIsolateThreadData into the ThreadDataTable
// (regardless of whether such data already exists). // (regardless of whether such data already exists).
PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id); PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
...@@ -1146,13 +1150,13 @@ class Isolate { ...@@ -1146,13 +1150,13 @@ class Isolate {
// the Error object. // the Error object.
bool IsErrorObject(Handle<Object> obj); bool IsErrorObject(Handle<Object> obj);
EntryStackItem* entry_stack_;
int stack_trace_nesting_level_; int stack_trace_nesting_level_;
StringStream* incomplete_message_; StringStream* incomplete_message_;
// The preallocated memory thread singleton. // The preallocated memory thread singleton.
PreallocatedMemoryThread* preallocated_memory_thread_; PreallocatedMemoryThread* preallocated_memory_thread_;
Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT
NoAllocationStringAllocator* preallocated_message_space_; NoAllocationStringAllocator* preallocated_message_space_;
Bootstrapper* bootstrapper_; Bootstrapper* bootstrapper_;
RuntimeProfiler* runtime_profiler_; RuntimeProfiler* runtime_profiler_;
CompilationCache* compilation_cache_; CompilationCache* compilation_cache_;
...@@ -1161,7 +1165,6 @@ class Isolate { ...@@ -1161,7 +1165,6 @@ class Isolate {
Mutex* break_access_; Mutex* break_access_;
Atomic32 debugger_initialized_; Atomic32 debugger_initialized_;
Mutex* debugger_access_; Mutex* debugger_access_;
Heap heap_;
Logger* logger_; Logger* logger_;
StackGuard stack_guard_; StackGuard stack_guard_;
StatsTable* stats_table_; StatsTable* stats_table_;
...@@ -1202,11 +1205,8 @@ class Isolate { ...@@ -1202,11 +1205,8 @@ class Isolate {
unibrow::Mapping<unibrow::Ecma262Canonicalize> unibrow::Mapping<unibrow::Ecma262Canonicalize>
regexp_macro_assembler_canonicalize_; regexp_macro_assembler_canonicalize_;
RegExpStack* regexp_stack_; RegExpStack* regexp_stack_;
DateCache* date_cache_; DateCache* date_cache_;
unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_; unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
void* embedder_data_;
// The garbage collector should be a little more aggressive when it knows // The garbage collector should be a little more aggressive when it knows
// that a context was recently exited. // that a context was recently exited.
......
...@@ -244,7 +244,7 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { ...@@ -244,7 +244,7 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
"Isolate::" #hacker_name "_address", "Isolate::" #hacker_name "_address",
FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL) FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL)
NULL NULL
#undef C #undef BUILD_NAME_LITERAL
}; };
for (uint16_t i = 0; i < Isolate::kIsolateAddressCount; ++i) { for (uint16_t i = 0; i < Isolate::kIsolateAddressCount; ++i) {
......
...@@ -16448,3 +16448,59 @@ TEST(SecondaryStubCache) { ...@@ -16448,3 +16448,59 @@ TEST(SecondaryStubCache) {
TEST(PrimaryStubCache) { TEST(PrimaryStubCache) {
StubCacheHelper(false); StubCacheHelper(false);
} }
TEST(StaticGetters) {
v8::HandleScope scope;
LocalContext context;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
i::Handle<i::Object> undefined_value = FACTORY->undefined_value();
CHECK(*v8::Utils::OpenHandle(*v8::Undefined()) == *undefined_value);
CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
i::Handle<i::Object> null_value = FACTORY->null_value();
CHECK(*v8::Utils::OpenHandle(*v8::Null()) == *null_value);
CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
i::Handle<i::Object> true_value = FACTORY->true_value();
CHECK(*v8::Utils::OpenHandle(*v8::True()) == *true_value);
CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
i::Handle<i::Object> false_value = FACTORY->false_value();
CHECK(*v8::Utils::OpenHandle(*v8::False()) == *false_value);
CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
}
static int fatal_error_callback_counter = 0;
static void CountingErrorCallback(const char* location, const char* message) {
printf("CountingErrorCallback(\"%s\", \"%s\")\n", location, message);
fatal_error_callback_counter++;
}
TEST(StaticGettersAfterDeath) {
v8::HandleScope scope;
LocalContext context;
v8::Isolate* isolate = v8::Isolate::GetCurrent();
CHECK(i::Internals::IsInitialized(isolate));
CHECK_EQ(0, fatal_error_callback_counter);
v8::V8::SetFatalErrorHandler(CountingErrorCallback);
v8::Utils::ReportApiFailure("StaticGettersAfterDeath()", "Kill V8");
i::Isolate::Current()->TearDown();
CHECK(!i::Internals::IsInitialized(isolate));
CHECK_EQ(1, fatal_error_callback_counter);
CHECK(v8::Undefined().IsEmpty());
CHECK_EQ(2, fatal_error_callback_counter);
CHECK(v8::Undefined(isolate).IsEmpty());
CHECK_EQ(3, fatal_error_callback_counter);
CHECK(v8::Null().IsEmpty());
CHECK_EQ(4, fatal_error_callback_counter);
CHECK(v8::Null(isolate).IsEmpty());
CHECK_EQ(5, fatal_error_callback_counter);
CHECK(v8::True().IsEmpty());
CHECK_EQ(6, fatal_error_callback_counter);
CHECK(v8::True(isolate).IsEmpty());
CHECK_EQ(7, fatal_error_callback_counter);
CHECK(v8::False().IsEmpty());
CHECK_EQ(8, fatal_error_callback_counter);
CHECK(v8::False(isolate).IsEmpty());
CHECK_EQ(9, fatal_error_callback_counter);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment