Revision: 11417
Author: [email protected]
Date: Mon Apr 23 08:09:59 2012
Log: Make static API getters inlineable again.
This relands r11376 with minor fixes for Windows where offsets are
slightly different from Linux for unaligned fields.
[email protected]
TEST=cctest/test-api/StaticGetters
Review URL: https://chromiumcodereview.appspot.com/10176004
http://code.google.com/p/v8/source/detail?r=11417
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/serialize.cc
/branches/bleeding_edge/test/cctest/test-api.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Wed Apr 18 10:49:53 2012
+++ /branches/bleeding_edge/include/v8.h Mon Apr 23 08:09:59 2012
@@ -2561,6 +2561,11 @@
Handle<Boolean> V8EXPORT True();
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.
@@ -3872,18 +3877,6 @@
PlatformSmiTagging::kEncodablePointerMask;
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
* is necessary to implement inline functions in the v8 api. Don't
@@ -3895,8 +3888,7 @@
// the implementation of v8.
static const int kHeapObjectMapOffset = 0;
static const int kMapInstanceTypeOffset = 1 * kApiPointerSize +
kApiIntSize;
- static const int kStringResourceOffset =
- InternalConstants<kApiPointerSize>::kStringResourceOffset;
+ static const int kStringResourceOffset = 3 * kApiPointerSize;
static const int kOddballKindOffset = 3 * kApiPointerSize;
static const int kForeignAddressOffset = kApiPointerSize;
@@ -3904,6 +3896,14 @@
static const int kFullStringRepresentationMask = 0x07;
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 kFirstNonstringType = 0x80;
static const int kOddballType = 0x82;
@@ -3955,6 +3955,16 @@
int representation = (instance_type & kFullStringRepresentationMask);
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>
static inline T ReadField(Object* ptr, int offset) {
@@ -4376,6 +4386,42 @@
Local<Object> AccessorInfo::Holder() const {
return Local<Object>(reinterpret_cast<Object*>(&args_[-1]));
}
+
+
+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));
+}
/**
=======================================
--- /branches/bleeding_edge/src/heap.h Mon Apr 23 06:59:43 2012
+++ /branches/bleeding_edge/src/heap.h Mon Apr 23 08:09:59 2012
@@ -1419,6 +1419,11 @@
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(
Object* number, bool check_number_string_cache = true);
MUST_USE_RESULT MaybeObject* Uint32ToString(
@@ -1613,6 +1618,8 @@
// more expedient to get at the isolate directly from within Heap
methods.
Isolate* isolate_;
+ Object* roots_[kRootListLength];
+
intptr_t code_range_size_;
int reserved_semispace_size_;
int max_semispace_size_;
@@ -1728,8 +1735,6 @@
// last GC.
int old_gen_exhausted_;
- Object* roots_[kRootListLength];
-
Object* global_contexts_list_;
StoreBufferRebuilder store_buffer_rebuilder_;
=======================================
--- /branches/bleeding_edge/src/isolate.cc Fri Apr 20 07:12:49 2012
+++ /branches/bleeding_edge/src/isolate.cc Mon Apr 23 08:09:59 2012
@@ -1430,6 +1430,7 @@
Isolate::Isolate()
: state_(UNINITIALIZED),
+ embedder_data_(NULL),
entry_stack_(NULL),
stack_trace_nesting_level_(0),
incomplete_message_(NULL),
@@ -1472,7 +1473,6 @@
string_tracker_(NULL),
regexp_stack_(NULL),
date_cache_(NULL),
- embedder_data_(NULL),
context_exit_happened_(false) {
TRACE_ISOLATE(constructor);
@@ -1856,6 +1856,13 @@
LOG(this, LogCodeObjects());
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;
time_millis_at_init_ = OS::TimeCurrentMillis();
=======================================
--- /branches/bleeding_edge/src/isolate.h Wed Apr 18 10:49:53 2012
+++ /branches/bleeding_edge/src/isolate.h Mon Apr 23 08:09:59 2012
@@ -422,7 +422,7 @@
enum AddressId {
#define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
-#undef C
+#undef DECLARE_ENUM
kIsolateAddressCount
};
@@ -1038,6 +1038,18 @@
friend struct GlobalState;
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
// modified.
class ThreadDataTable {
@@ -1095,14 +1107,6 @@
static void SetIsolateThreadLocals(Isolate* isolate,
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
// (regardless of whether such data already exists).
PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
@@ -1146,13 +1150,13 @@
// the Error object.
bool IsErrorObject(Handle<Object> obj);
+ EntryStackItem* entry_stack_;
int stack_trace_nesting_level_;
StringStream* incomplete_message_;
// The preallocated memory thread singleton.
PreallocatedMemoryThread* preallocated_memory_thread_;
Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT
NoAllocationStringAllocator* preallocated_message_space_;
-
Bootstrapper* bootstrapper_;
RuntimeProfiler* runtime_profiler_;
CompilationCache* compilation_cache_;
@@ -1161,7 +1165,6 @@
Mutex* break_access_;
Atomic32 debugger_initialized_;
Mutex* debugger_access_;
- Heap heap_;
Logger* logger_;
StackGuard stack_guard_;
StatsTable* stats_table_;
@@ -1202,11 +1205,8 @@
unibrow::Mapping<unibrow::Ecma262Canonicalize>
regexp_macro_assembler_canonicalize_;
RegExpStack* regexp_stack_;
-
DateCache* date_cache_;
-
unibrow::Mapping<unibrow::Ecma262Canonicalize>
interp_canonicalize_mapping_;
- void* embedder_data_;
// The garbage collector should be a little more aggressive when it knows
// that a context was recently exited.
=======================================
--- /branches/bleeding_edge/src/serialize.cc Fri Apr 20 07:12:49 2012
+++ /branches/bleeding_edge/src/serialize.cc Mon Apr 23 08:09:59 2012
@@ -244,7 +244,7 @@
"Isolate::" #hacker_name "_address",
FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL)
NULL
-#undef C
+#undef BUILD_NAME_LITERAL
};
for (uint16_t i = 0; i < Isolate::kIsolateAddressCount; ++i) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Fri Apr 20 06:35:09 2012
+++ /branches/bleeding_edge/test/cctest/test-api.cc Mon Apr 23 08:09:59 2012
@@ -16448,3 +16448,59 @@
TEST(PrimaryStubCache) {
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);
+}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev