#include "cctest.h"
#include "debug.h"
+enum InitializationState {kUnset, kUnintialized, kInitialized};
+static InitializationState initialization_state_ = kUnset;
CcTest* CcTest::last_ = NULL;
-CcTest::InitializationState CcTest::initialization_state_ = kUnset;
+bool CcTest::initialize_called_ = false;
+bool CcTest::isolate_used_ = false;
+v8::Isolate* CcTest::isolate_ = NULL;
+
CcTest::CcTest(TestFunction* callback, const char* file, const char* name,
const char* dependency, bool enabled, bool initialize)
CHECK(initialization_state_ != kInitialized);
initialization_state_ = kUnintialized;
// TODO(dcarney): Remove this when default isolate is gone.
- if (default_isolate_ == NULL) {
- default_isolate_ = v8::Isolate::GetCurrent();
+ if (isolate_ == NULL) {
+ isolate_ = v8::Isolate::GetCurrent();
}
} else {
CHECK(initialization_state_ != kUnintialized);
initialization_state_ = kInitialized;
i::Isolate::SetCrashIfDefaultIsolateInitialized();
- if (default_isolate_ == NULL) {
- default_isolate_ = v8::Isolate::New();
+ if (isolate_ == NULL) {
+ isolate_ = v8::Isolate::New();
}
- default_isolate_->Enter();
+ isolate_->Enter();
}
callback_();
if (initialize_) {
- default_isolate_->Exit();
+ isolate_->Exit();
}
}
-v8::Persistent<v8::Context> CcTest::context_;
-
-
-void CcTest::InitializeVM(CcTestExtensionFlags extensions) {
- const char* extension_names[kMaxExtensions];
- int extension_count = 0;
-#define CHECK_EXTENSION_FLAG(Name, Id) \
- if (extensions.Contains(Name##_ID)) extension_names[extension_count++] = Id;
- EXTENSION_LIST(CHECK_EXTENSION_FLAG)
-#undef CHECK_EXTENSION_FLAG
- v8::Isolate* isolate = CcTest::isolate();
- if (context_.IsEmpty()) {
- v8::HandleScope scope(isolate);
+v8::Local<v8::Context> CcTest::NewContext(CcTestExtensionFlags extensions,
+ v8::Isolate* isolate) {
+ const char* extension_names[kMaxExtensions];
+ int extension_count = 0;
+ #define CHECK_EXTENSION_FLAG(Name, Id) \
+ if (extensions.Contains(Name##_ID)) extension_names[extension_count++] = Id;
+ EXTENSION_LIST(CHECK_EXTENSION_FLAG)
+ #undef CHECK_EXTENSION_FLAG
v8::ExtensionConfiguration config(extension_count, extension_names);
v8::Local<v8::Context> context = v8::Context::New(isolate, &config);
- context_.Reset(isolate, context);
- }
- {
- v8::HandleScope scope(isolate);
- v8::Local<v8::Context> context =
- v8::Local<v8::Context>::New(isolate, context_);
- context->Enter();
- }
+ CHECK(!context.IsEmpty());
+ return context;
}
}
-v8::Isolate* CcTest::default_isolate_ = NULL;
-
-
class CcTestArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
virtual void* Allocate(size_t length) { return malloc(length); }
virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
const char* dependency() { return dependency_; }
bool enabled() { return enabled_; }
- static v8::Handle<v8::Context> env() {
- return v8::Local<v8::Context>::New(isolate(), context_);
- }
-
static v8::Isolate* isolate() {
- return default_isolate_;
+ isolate_used_ = true;
+ return isolate_;
}
static i::Isolate* i_isolate() {
return i_isolate()->heap();
}
- // Helper function to initialize the VM.
- static void InitializeVM(CcTestExtensionFlags extensions = NO_EXTENSIONS);
+ // TODO(dcarney): Remove.
+ // This must be called first in a test.
+ static void InitializeVM() {
+ CHECK(!isolate_used_);
+ CHECK(!initialize_called_);
+ initialize_called_ = true;
+ v8::HandleScope handle_scope(CcTest::isolate());
+ v8::Context::New(CcTest::isolate())->Enter();
+ }
+
+ // Helper function to configure a context.
+ // Must be in a HandleScope.
+ static v8::Local<v8::Context> NewContext(
+ CcTestExtensionFlags extensions,
+ v8::Isolate* isolate = CcTest::isolate());
private:
friend int main(int argc, char** argv);
bool initialize_;
CcTest* prev_;
static CcTest* last_;
- static v8::Isolate* default_isolate_;
- enum InitializationState {kUnset, kUnintialized, kInitialized};
- static InitializationState initialization_state_;
- static v8::Persistent<v8::Context> context_;
+ static v8::Isolate* isolate_;
+ static bool initialize_called_;
+ static bool isolate_used_;
};
// Switches between all the Api tests using the threading support.
double value,
int expected,
bool expected_exception = false) {
- CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
TEST(7) {
+ CcTest::InitializeVM();
// Test vfp rounding modes.
// s32_f64 (double to integer).
#define ELEMENT_COUNT 4
void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
- CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::internal::byte buffer[1024];
TEST(StackAlignmentForSSE2) {
+ CcTest::InitializeVM();
CHECK_EQ(0, OS::ActivationFrameAlignment() % 16);
v8::Isolate* isolate = CcTest::isolate();
TEST(Print) {
- CcTest::InitializeVM(PRINT_EXTENSION);
v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
+ v8::Context::Scope context_scope(context);
const char* source = "for (n = 0; n < 100; ++n) print(n, 1, 2);";
Handle<JSFunction> fun = Compile(source);
if (fun.is_null()) return;
// | JS |
// | C-to-JS |
TEST(C2JSFrames) {
- CcTest::InitializeVM(PRINT_EXTENSION | GC_EXTENSION);
v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context =
+ CcTest::NewContext(PRINT_EXTENSION | GC_EXTENSION);
+ v8::Context::Scope context_scope(context);
const char* source = "function foo(a) { gc(), print(a); }";
TEST(GetScriptLineNumber) {
- CcTest::InitializeVM();
+ LocalContext context;
v8::HandleScope scope(CcTest::isolate());
v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
const char function_f[] = "function f() {}";
v8::Handle<v8::String> script_body = v8::String::New(buffer.start());
v8::Script::Compile(script_body, &origin)->Run();
v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
- CcTest::env()->Global()->Get(v8::String::New("f")));
+ context->Global()->Get(v8::String::New("f")));
CHECK_EQ(i, f->GetScriptLineNumber());
}
}
TEST(SplitConstantsInFullCompiler) {
- CcTest::InitializeVM();
+ LocalContext context;
v8::HandleScope scope(CcTest::isolate());
CompileRun("function f() { a = 12345678 }; f();");
- CheckCodeForUnsafeLiteral(GetJSFunction(CcTest::env()->Global(), "f"));
+ CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
CompileRun("function f(x) { a = 12345678 + x}; f(1);");
- CheckCodeForUnsafeLiteral(GetJSFunction(CcTest::env()->Global(), "f"));
+ CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
CompileRun("function f(x) { var arguments = 1; x += 12345678}; f(1);");
- CheckCodeForUnsafeLiteral(GetJSFunction(CcTest::env()->Global(), "f"));
+ CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
CompileRun("function f(x) { var arguments = 1; x = 12345678}; f(1);");
- CheckCodeForUnsafeLiteral(GetJSFunction(CcTest::env()->Global(), "f"));
+ CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
}
#endif
// resource's callback is fired when the external string is GC'ed.
FLAG_use_ic = false; // ICs retain objects.
FLAG_concurrent_recompilation = false;
- CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
SourceResource* resource = new SourceResource(i::StrDup(source));
{
TEST(ReleaseStackTraceData) {
+ CcTest::InitializeVM();
static const char* source1 = "var error = null; "
/* Normal Error */ "try { "
" throw new Error(); "
}
-static bool IsAddressWithinFuncCode(const char* func_name, Address addr) {
- v8::Local<v8::Value> func = CcTest::env()->Global()->Get(v8_str(func_name));
+static bool IsAddressWithinFuncCode(v8::Local<v8::Context> context,
+ const char* func_name,
+ Address addr) {
+ v8::Local<v8::Value> func = context->Global()->Get(v8_str(func_name));
CHECK(func->IsFunction());
JSFunction* js_func = JSFunction::cast(*v8::Utils::OpenHandle(*func));
return IsAddressWithinFuncCode(js_func, addr);
// Use the API to create a JSFunction object that calls the above C++ function.
-void CreateFramePointerGrabberConstructor(const char* constructor_name) {
+void CreateFramePointerGrabberConstructor(v8::Local<v8::Context> context,
+ const char* constructor_name) {
Local<v8::FunctionTemplate> constructor_template =
v8::FunctionTemplate::New(construct_call);
constructor_template->SetClassName(v8_str("FPGrabber"));
Local<Function> fun = constructor_template->GetFunction();
- CcTest::env()->Global()->Set(v8_str(constructor_name), fun);
+ context->Global()->Set(v8_str(constructor_name), fun);
}
// Creates a global function named 'func_name' that calls the tracing
// function 'trace_func_name' with an actual EBP register value,
// encoded as one or two Smis.
-static void CreateTraceCallerFunction(const char* func_name,
+static void CreateTraceCallerFunction(v8::Local<v8::Context> context,
+ const char* func_name,
const char* trace_func_name) {
i::EmbeddedVector<char, 256> trace_call_buf;
i::OS::SNPrintF(trace_call_buf,
// Create the FPGrabber function, which grabs the caller's frame pointer
// when called as a constructor.
- CreateFramePointerGrabberConstructor("FPGrabber");
+ CreateFramePointerGrabberConstructor(context, "FPGrabber");
// Compile the script.
CompileRun(trace_call_buf.start());
TickSample sample;
InitTraceEnv(&sample);
- CcTest::InitializeVM(TRACE_EXTENSION);
v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
+ v8::Context::Scope context_scope(context);
+
// Create global function JSFuncDoTrace which calls
// extension function trace() with the current frame pointer value.
- CreateTraceCallerFunction("JSFuncDoTrace", "trace");
+ CreateTraceCallerFunction(context, "JSFuncDoTrace", "trace");
Local<Value> result = CompileRun(
"function JSTrace() {"
" JSFuncDoTrace();"
int base = 0;
CHECK_GT(sample.frames_count, base + 1);
- CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0]));
- CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1]));
+ CHECK(IsAddressWithinFuncCode(
+ context, "JSFuncDoTrace", sample.stack[base + 0]));
+ CHECK(IsAddressWithinFuncCode(context, "JSTrace", sample.stack[base + 1]));
}
TickSample sample;
InitTraceEnv(&sample);
- CcTest::InitializeVM(TRACE_EXTENSION);
v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
+ v8::Context::Scope context_scope(context);
+
// Create global function JSFuncDoTrace which calls
// extension function js_trace() with the current frame pointer value.
- CreateTraceCallerFunction("JSFuncDoTrace", "js_trace");
+ CreateTraceCallerFunction(context, "JSFuncDoTrace", "js_trace");
Local<Value> result = CompileRun(
"function JSTrace() {"
" JSFuncDoTrace();"
// Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
int base = 0;
CHECK_GT(sample.frames_count, base + 1);
- CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 0]));
- CHECK(IsAddressWithinFuncCode("OuterJSTrace", sample.stack[base + 1]));
+ CHECK(IsAddressWithinFuncCode(context, "JSTrace", sample.stack[base + 0]));
+ CHECK(IsAddressWithinFuncCode(
+ context, "OuterJSTrace", sample.stack[base + 1]));
}
TEST(PureCStackTrace) {
TickSample sample;
InitTraceEnv(&sample);
- CcTest::InitializeVM(TRACE_EXTENSION);
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
+ v8::Context::Scope context_scope(context);
// Check that sampler doesn't crash
CHECK_EQ(10, CFunc(10));
}
TEST(JsEntrySp) {
- CcTest::InitializeVM(TRACE_EXTENSION);
v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
+ v8::Context::Scope context_scope(context);
CHECK_EQ(0, GetJsEntrySp());
CompileRun("a = 1; b = a + 1;");
CHECK_EQ(0, GetJsEntrySp());
// skip the entire test.
if (FLAG_never_compact) return;
+ CcTest::InitializeVM();
+
// Ensure that we get a compacting collection so that objects are promoted
// from new space.
FLAG_gc_global = true;
Heap* heap = CcTest::heap();
heap->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
- CcTest::InitializeVM();
-
v8::HandleScope sc(CcTest::isolate());
// Allocate a fixed array in the new space.
TEST(NoPromotion) {
- CcTest::heap()->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
-
// Test the situation that some objects in new space are promoted to
// the old space
CcTest::InitializeVM();
+ CcTest::heap()->ConfigureHeap(2*256*KB, 8*MB, 8*MB);
+
v8::HandleScope sc(CcTest::isolate());
// Do a mark compact GC to shrink the heap.
Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate);
- CcTest::InitializeVM();
+ LocalContext context;
v8::HandleScope handle_scope(CcTest::isolate());
// Make sure we cover all always-flat lengths and at least one above.
}
// Add the arrays with the short external strings in the global object.
- v8::Handle<v8::Object> global = CcTest::env()->Global();
+ v8::Handle<v8::Object> global = context->Global();
global->Set(v8_str("external_ascii"), ascii_external_strings);
global->Set(v8_str("external_non_ascii"), non_ascii_external_strings);
global->Set(v8_str("max_length"), v8::Integer::New(kMaxLength));
TEST(JSONStringifySliceMadeExternal) {
+ CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate);
- CcTest::InitializeVM();
// Create a sliced string from a one-byte string. The latter is turned
// into a two-byte external string. Check that JSON.stringify works.
v8::HandleScope handle_scope(CcTest::isolate());
TEST(CachedHashOverflow) {
+ CcTest::InitializeVM();
// We incorrectly allowed strings to be tagged as array indices even if their
// values didn't fit in the hash field.
// See http://code.google.com/p/v8/issues/detail?id=728
Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate);
- CcTest::InitializeVM();
v8::HandleScope handle_scope(CcTest::isolate());
// Lines must be executed sequentially. Combining them into one script
// makes the bug go away.