Author: [email protected]
Date: Mon Feb 23 05:59:59 2009
New Revision: 1339
Modified:
branches/experimental/toiger/ (props changed)
branches/experimental/toiger/src/codegen-arm.cc
branches/experimental/toiger/src/d8.cc
branches/experimental/toiger/src/log.cc
branches/experimental/toiger/src/platform-freebsd.cc
branches/experimental/toiger/src/platform-linux.cc
branches/experimental/toiger/src/platform-macos.cc
branches/experimental/toiger/src/platform-win32.cc
branches/experimental/toiger/src/platform.h
branches/experimental/toiger/src/regexp-macro-assembler-ia32.cc
branches/experimental/toiger/src/regexp-macro-assembler-ia32.h
branches/experimental/toiger/src/regexp-macro-assembler-irregexp-inl.h
(props changed)
branches/experimental/toiger/test/cctest/test-api.cc
branches/experimental/toiger/test/mjsunit/global-load-from-eval-in-with.js
(props changed)
branches/experimental/toiger/test/mjsunit/local-load-from-eval.js
(props changed)
branches/experimental/toiger/test/mjsunit/property-load-across-eval.js
(props changed)
branches/experimental/toiger/test/mjsunit/toint32.js
branches/experimental/toiger/tools/tickprocessor.py
Log:
Experimental: periodic merge from the bleeding edge to the
experimental code generator branch. Merge up to and including
bleeding_e...@1338.
Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc (original)
+++ branches/experimental/toiger/src/codegen-arm.cc Mon Feb 23 05:59:59 2009
@@ -2086,6 +2086,7 @@
// been dropped.
__ ldr(r1, frame_->ElementAt(kNextIndex - 1));
__ str(r1, MemOperand(r3));
+ // The code slot has already been dropped from the handler.
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
Modified: branches/experimental/toiger/src/d8.cc
==============================================================================
--- branches/experimental/toiger/src/d8.cc (original)
+++ branches/experimental/toiger/src/d8.cc Mon Feb 23 05:59:59 2009
@@ -419,8 +419,8 @@
}
-static char* ReadToken(const char* data, char token) {
- char* next = ::strchr(data, token);
+static char* ReadToken(char* data, char token) {
+ char* next = i::OS::StrChr(data, token);
if (next != NULL) {
*next = '\0';
return (next + 1);
@@ -430,12 +430,12 @@
}
-static char* ReadLine(const char* data) {
+static char* ReadLine(char* data) {
return ReadToken(data, '\n');
}
-static char* ReadWord(const char* data) {
+static char* ReadWord(char* data) {
return ReadToken(data, ' ');
}
Modified: branches/experimental/toiger/src/log.cc
==============================================================================
--- branches/experimental/toiger/src/log.cc (original)
+++ branches/experimental/toiger/src/log.cc Mon Feb 23 05:59:59 2009
@@ -679,6 +679,7 @@
}
+#ifdef ENABLE_LOGGING_AND_PROFILING
int Logger::CodeObjectSize(Code* code) {
// Check that the assumptions about the layout of the code object holds.
ASSERT_EQ(reinterpret_cast<unsigned int>(code->instruction_start()) -
@@ -686,6 +687,7 @@
Code::kHeaderSize);
return code->instruction_size() + Code::kHeaderSize;
}
+#endif
void Logger::CodeCreateEvent(const char* tag, Code* code, const char*
comment) {
Modified: branches/experimental/toiger/src/platform-freebsd.cc
==============================================================================
--- branches/experimental/toiger/src/platform-freebsd.cc (original)
+++ branches/experimental/toiger/src/platform-freebsd.cc Mon Feb 23
05:59:59 2009
@@ -184,6 +184,11 @@
}
+char* OS::StrChr(char* str, int c) {
+ return strchr(str, c);
+}
+
+
void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
strncpy(dest.start(), src, n);
}
Modified: branches/experimental/toiger/src/platform-linux.cc
==============================================================================
--- branches/experimental/toiger/src/platform-linux.cc (original)
+++ branches/experimental/toiger/src/platform-linux.cc Mon Feb 23 05:59:59
2009
@@ -180,6 +180,11 @@
}
+char* OS::StrChr(char* str, int c) {
+ return strchr(str, c);
+}
+
+
void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
strncpy(dest.start(), src, n);
}
Modified: branches/experimental/toiger/src/platform-macos.cc
==============================================================================
--- branches/experimental/toiger/src/platform-macos.cc (original)
+++ branches/experimental/toiger/src/platform-macos.cc Mon Feb 23 05:59:59
2009
@@ -185,6 +185,11 @@
}
+char* OS::StrChr(char* str, int c) {
+ return strchr(str, c);
+}
+
+
void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
strncpy(dest.start(), src, n);
}
Modified: branches/experimental/toiger/src/platform-win32.cc
==============================================================================
--- branches/experimental/toiger/src/platform-win32.cc (original)
+++ branches/experimental/toiger/src/platform-win32.cc Mon Feb 23 05:59:59
2009
@@ -732,6 +732,11 @@
}
+char* OS::StrChr(char* str, int c) {
+ return const_cast<char*>(strchr(str, c));
+}
+
+
void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
int result = strncpy_s(dest.start(), dest.length(), src, n);
USE(result);
Modified: branches/experimental/toiger/src/platform.h
==============================================================================
--- branches/experimental/toiger/src/platform.h (original)
+++ branches/experimental/toiger/src/platform.h Mon Feb 23 05:59:59 2009
@@ -219,6 +219,7 @@
const char* format,
va_list args);
+ static char* StrChr(char* str, int c);
static void StrNCpy(Vector<char> dest, const char* src, size_t n);
static char* StrDup(const char* str);
static char* StrNDup(const char* str, size_t n);
Modified: branches/experimental/toiger/src/regexp-macro-assembler-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/regexp-macro-assembler-ia32.cc
(original)
+++ branches/experimental/toiger/src/regexp-macro-assembler-ia32.cc Mon Feb
23 05:59:59 2009
@@ -1046,7 +1046,7 @@
}
-int RegExpMacroAssemblerIA32::CheckStackGuardState(Address return_address,
+int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
Code* re_code) {
if (StackGuard::IsStackOverflow()) {
Top::StackOverflow();
@@ -1059,15 +1059,16 @@
// Prepare for possible GC.
Handle<Code> code_handle(re_code);
- ASSERT(re_code->instruction_start() <= return_address);
- ASSERT(return_address <=
+ ASSERT(re_code->instruction_start() <= *return_address);
+ ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
Object* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid
int delta = *code_handle - re_code;
- *reinterpret_cast<int32_t*>(return_address) += delta;
+ // Overwrite the return address on the stack.
+ *return_address += delta;
}
if (result->IsException()) {
Modified: branches/experimental/toiger/src/regexp-macro-assembler-ia32.h
==============================================================================
--- branches/experimental/toiger/src/regexp-macro-assembler-ia32.h
(original)
+++ branches/experimental/toiger/src/regexp-macro-assembler-ia32.h Mon Feb
23 05:59:59 2009
@@ -166,7 +166,7 @@
// Called from RegExp if the stack-guard is triggered.
// If the code object is relocated, the return address is fixed before
// returning.
- static int CheckStackGuardState(Address return_address, Code* re_code);
+ static int CheckStackGuardState(Address* return_address, Code* re_code);
// Called from RegExp if the backtrack stack limit is hit.
// Tries to expand the stack. Returns the new stack-pointer if
Modified: branches/experimental/toiger/test/cctest/test-api.cc
==============================================================================
--- branches/experimental/toiger/test/cctest/test-api.cc (original)
+++ branches/experimental/toiger/test/cctest/test-api.cc Mon Feb 23
05:59:59 2009
@@ -5658,3 +5658,123 @@
context0.Dispose();
context1.Dispose();
}
+
+
+class RegExpInterruptTest {
+ public:
+ void RunTest() {
+ block_ = i::OS::CreateSemaphore(0);
+ gc_count_ = 0;
+ gc_during_regexp_ = 0;
+ regexp_success_ = false;
+ gc_success_ = false;
+ GCThread gc_thread(this);
+ gc_thread.Start();
+ v8::Locker::StartPreemption(1);
+
+ LongRunningRegExp();
+ {
+ v8::Unlocker unlock;
+ gc_thread.Join();
+ }
+ v8::Locker::StopPreemption();
+ CHECK(regexp_success_);
+ CHECK(gc_success_);
+ }
+ private:
+ // Number of garbage collections required.
+ static const int kRequiredGCs = 5;
+
+ class GCThread : public i::Thread {
+ public:
+ explicit GCThread(RegExpInterruptTest* test)
+ : test_(test) {}
+ virtual void Run() {
+ test_->CollectGarbage();
+ }
+ private:
+ RegExpInterruptTest* test_;
+ };
+
+ void CollectGarbage() {
+ block_->Wait();
+ while (gc_during_regexp_ < kRequiredGCs) {
+ {
+ v8::Locker lock;
+ // TODO(lrn): Perhaps create some garbage before collecting.
+ i::Heap::CollectAllGarbage();
+ gc_count_++;
+ }
+ i::OS::Sleep(1);
+ }
+ gc_success_ = true;
+ }
+
+ void LongRunningRegExp() {
+ block_->Signal(); // Enable garbage collection thread on next
preemption.
+ int rounds = 0;
+ while (gc_during_regexp_ < kRequiredGCs) {
+ int gc_before = gc_count_;
+ {
+ // match 15-30 "a"'s against 14 and a "b".
+ const char* c_source =
+ "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+ ".exec('aaaaaaaaaaaaaaab') === null";
+ Local<String> source = String::New(c_source);
+ Local<Script> script = Script::Compile(source);
+ Local<Value> result = script->Run();
+ if (!result->BooleanValue()) {
+ gc_during_regexp_ = kRequiredGCs; // Allow gc thread to exit.
+ return;
+ }
+ }
+ {
+ // match 15-30 "a"'s against 15 and a "b".
+ const char* c_source =
+ "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
+ ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
+ Local<String> source = String::New(c_source);
+ Local<Script> script = Script::Compile(source);
+ Local<Value> result = script->Run();
+ if (!result->BooleanValue()) {
+ gc_during_regexp_ = kRequiredGCs;
+ return;
+ }
+ }
+ int gc_after = gc_count_;
+ gc_during_regexp_ += gc_after - gc_before;
+ rounds++;
+ i::OS::Sleep(1);
+ }
+ regexp_success_ = true;
+ }
+
+ i::Semaphore* block_;
+ int gc_count_;
+ int gc_during_regexp_;
+ bool regexp_success_;
+ bool gc_success_;
+};
+
+
+// Test that a regular expression execution can be interrupted and
+// survive a garbage collection.
+TEST(RegExpInterruption) {
+ v8::Locker lock;
+ v8::V8::Initialize();
+ v8::HandleScope scope;
+ Local<Context> local_env;
+ {
+ LocalContext env;
+ local_env = env.local();
+ }
+
+ // Local context should still be live.
+ CHECK(!local_env.IsEmpty());
+ local_env->Enter();
+
+ // Should complete without problems.
+ RegExpInterruptTest().RunTest();
+
+ local_env->Exit();
+}
Modified: branches/experimental/toiger/test/mjsunit/toint32.js
==============================================================================
--- branches/experimental/toiger/test/mjsunit/toint32.js (original)
+++ branches/experimental/toiger/test/mjsunit/toint32.js Mon Feb 23
05:59:59 2009
@@ -42,6 +42,10 @@
assertEquals(1, toInt32(1));
assertEquals(1, toInt32(1.1));
assertEquals(-1, toInt32(-1));
+assertEquals(0, toInt32(0.6), "truncate positive (0.6)");
+assertEquals(1, toInt32(1.6), "truncate positive (1.6)");
+assertEquals(0, toInt32(-0.6), "truncate negative (-0.6)");
+assertEquals(-1, toInt32(-1.6), "truncate negative (-1.6)");
assertEquals(2147483647, toInt32(2147483647));
assertEquals(-2147483648, toInt32(2147483648));
@@ -78,3 +82,48 @@
assertEquals(1294967296, toInt32(-3000000000.25));
assertEquals(1294967296, toInt32(-3000000000.5));
assertEquals(1294967296, toInt32(-3000000000.75));
+
+var base = Math.pow(2, 64);
+assertEquals(0, toInt32(base + 0));
+assertEquals(0, toInt32(base + 1117));
+assertEquals(4096, toInt32(base + 2234));
+assertEquals(4096, toInt32(base + 3351));
+assertEquals(4096, toInt32(base + 4468));
+assertEquals(4096, toInt32(base + 5585));
+assertEquals(8192, toInt32(base + 6702));
+assertEquals(8192, toInt32(base + 7819));
+assertEquals(8192, toInt32(base + 8936));
+assertEquals(8192, toInt32(base + 10053));
+assertEquals(12288, toInt32(base + 11170));
+assertEquals(12288, toInt32(base + 12287));
+assertEquals(12288, toInt32(base + 13404));
+assertEquals(16384, toInt32(base + 14521));
+assertEquals(16384, toInt32(base + 15638));
+assertEquals(16384, toInt32(base + 16755));
+assertEquals(16384, toInt32(base + 17872));
+assertEquals(20480, toInt32(base + 18989));
+assertEquals(20480, toInt32(base + 20106));
+assertEquals(20480, toInt32(base + 21223));
+assertEquals(20480, toInt32(base + 22340));
+assertEquals(24576, toInt32(base + 23457));
+assertEquals(24576, toInt32(base + 24574));
+assertEquals(24576, toInt32(base + 25691));
+assertEquals(28672, toInt32(base + 26808));
+assertEquals(28672, toInt32(base + 27925));
+assertEquals(28672, toInt32(base + 29042));
+assertEquals(28672, toInt32(base + 30159));
+assertEquals(32768, toInt32(base + 31276));
+
+// bignum is (2^53 - 1) * 2^31 - highest number with bit 31 set.
+var bignum = Math.pow(2, 84) - Math.pow(2, 31);
+assertEquals(-Math.pow(2,31), toInt32(bignum));
+assertEquals(-Math.pow(2,31), toInt32(-bignum));
+assertEquals(0, toInt32(2 * bignum));
+assertEquals(0, toInt32(-(2 * bignum)));
+assertEquals(0, toInt32(bignum - Math.pow(2,31)));
+assertEquals(0, toInt32(-(bignum - Math.pow(2,31))));
+
+// max_fraction is largest number below 1.
+var max_fraction = (1 - Math.pow(2,-53));
+assertEquals(0, toInt32(max_fraction));
+assertEquals(0, toInt32(-max_fraction));
Modified: branches/experimental/toiger/tools/tickprocessor.py
==============================================================================
--- branches/experimental/toiger/tools/tickprocessor.py (original)
+++ branches/experimental/toiger/tools/tickprocessor.py Mon Feb 23 05:59:59
2009
@@ -386,9 +386,15 @@
total_stacks += count
all_stacks_items = all_stacks.items();
all_stacks_items.sort(key = itemgetter(1), reverse=True)
+ missing_percentage = (self.total_number_of_ticks - total_stacks) *
100.0 / self.total_number_of_ticks
+ print(' %(ticks)5d %(total)5.1f%% <no call path information>' % {
+ 'ticks' : self.total_number_of_ticks - total_stacks,
+ 'total' : missing_percentage
+ })
for stack, count in all_stacks_items:
- total_percentage = count * 100.0 / total_stacks
- print(' %(total)5.1f%% %(call_path)s' % {
+ total_percentage = count * 100.0 / self.total_number_of_ticks
+ print(' %(ticks)5d %(total)5.1f%% %(call_path)s' % {
+ 'ticks' : count,
'total' : total_percentage,
'call_path' : stack[0] + ' <- ' + stack[1]
})
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---