2013-11-22: Version 3.23.10
Remove preemption thread and API. (issue 3004)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@17998 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..8fa6b1a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,3 @@
+# Defines the Google C++ style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Google
diff --git a/ChangeLog b/ChangeLog
index 42ee840..73bfe96 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+ 2013-11-22: Version 3.23.10
+
+ Remove preemption thread and API.
+ (issue 3004)
+
+ Performance and stability improvements on all platforms.
+
+
2013-11-21: Version 3.23.9
API: Change AdjustAmountOfExternalAllocatedMemory calls to use int64_t
diff --git a/build/features.gypi b/build/features.gypi
index 08ea11a..85b8a38 100644
--- a/build/features.gypi
+++ b/build/features.gypi
@@ -58,6 +58,9 @@
# Enable compiler warnings when using V8_DEPRECATED apis.
'v8_deprecation_warnings%': 0,
+
+ # Use the v8 provided v8::Platform implementation.
+ 'v8_use_default_platform%': 1,
},
'target_defaults': {
'conditions': [
@@ -85,6 +88,9 @@
['v8_enable_i18n_support==1', {
'defines': ['V8_I18N_SUPPORT',],
}],
+ ['v8_use_default_platform==1', {
+ 'defines': ['V8_USE_DEFAULT_PLATFORM',],
+ }],
['v8_compress_startup_data=="bz2"', {
'defines': [
'COMPRESS_STARTUP_DATA_BZ2',
diff --git a/include/v8-platform.h b/include/v8-platform.h
new file mode 100644
index 0000000..75fddd5
--- /dev/null
+++ b/include/v8-platform.h
@@ -0,0 +1,86 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_V8_PLATFORM_H_
+#define V8_V8_PLATFORM_H_
+
+#include "v8.h"
+
+namespace v8 {
+
+/**
+ * A Task represents a unit of work.
+ */
+class Task {
+ public:
+ virtual ~Task() {}
+
+ virtual void Run() = 0;
+};
+
+/**
+ * V8 Platform abstraction layer.
+ *
+ * The embedder has to provide an implementation of this interface before
+ * initializing the rest of V8.
+ */
+class Platform {
+ public:
+ /**
+ * This enum is used to indicate whether a task is potentially long running,
+ * or causes a long wait. The embedder might want to use this hint to decide
+ * whether to execute the task on a dedicated thread.
+ */
+ enum ExpectedRuntime {
+ kShortRunningTask,
+ kLongRunningTask
+ };
+
+ /**
+ * Schedules a task to be invoked on a background thread. |expected_runtime|
+ * indicates that the task will run a long time. The Platform implementation
+ * takes ownership of |task|. There is no guarantee about order of execution
+ * of tasks wrt order of scheduling, nor is there a guarantee about the
+ * thread the task will be run on.
+ */
+ virtual void CallOnBackgroundThread(Task* task,
+ ExpectedRuntime expected_runtime) = 0;
+
+ /**
+ * Schedules a task to be invoked on a foreground thread wrt a specific
+ * |isolate|. Tasks posted for the same isolate should be execute in order of
+ * scheduling. The definition of "foreground" is opaque to V8.
+ */
+ virtual void CallOnForegroundThread(Isolate* isolate, Task* task) = 0;
+
+ protected:
+ virtual ~Platform() {}
+};
+
+} // namespace v8
+
+#endif // V8_V8_PLATFORM_H_
diff --git a/include/v8.h b/include/v8.h
index 6e227dd..e44c0bf 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -105,6 +105,7 @@
class Object;
class ObjectOperationDescriptor;
class ObjectTemplate;
+class Platform;
class Primitive;
class RawOperationDescriptor;
class Signature;
@@ -4798,6 +4799,18 @@
*/
static bool InitializeICU();
+ /**
+ * Sets the v8::Platform to use. This should be invoked before V8 is
+ * initialized.
+ */
+ static void InitializePlatform(Platform* platform);
+
+ /**
+ * Clears all references to the v8::Platform. This should be invoked after
+ * V8 was disposed.
+ */
+ static void ShutdownPlatform();
+
private:
V8();
@@ -5271,12 +5284,6 @@
~Locker();
- V8_DEPRECATED("This will be remvoed.",
- static void StartPreemption(Isolate *isolate, int every_n_ms));
-
- V8_DEPRECATED("This will be removed",
- static void StopPreemption(Isolate* isolate));
-
/**
* Returns whether or not the locker for a given isolate, is locked by the
* current thread.
diff --git a/src/api.cc b/src/api.cc
index a448e19..adc3e7a 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5045,6 +5045,24 @@
// --- E n v i r o n m e n t ---
+void v8::V8::InitializePlatform(Platform* platform) {
+#ifdef V8_USE_DEFAULT_PLATFORM
+ FATAL("Can't override v8::Platform when using default implementation");
+#else
+ i::V8::InitializePlatform(platform);
+#endif
+}
+
+
+void v8::V8::ShutdownPlatform() {
+#ifdef V8_USE_DEFAULT_PLATFORM
+ FATAL("Can't override v8::Platform when using default implementation");
+#else
+ i::V8::ShutdownPlatform();
+#endif
+}
+
+
bool v8::V8::Initialize() {
i::Isolate* isolate = i::Isolate::UncheckedCurrent();
if (isolate != NULL && isolate->IsInitialized()) {
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index bc52fa8..322df91 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -40,6 +40,7 @@
#include "objects-visiting.h"
#include "platform.h"
#include "snapshot.h"
+#include "trig-table.h"
#include "extensions/externalize-string-extension.h"
#include "extensions/gc-extension.h"
#include "extensions/statistics-extension.h"
@@ -2635,6 +2636,44 @@
InitializeExperimentalGlobal();
if (!InstallExperimentalNatives()) return;
+ if (!Serializer::enabled()) {
+ Handle<JSBuiltinsObject> builtins(native_context()->builtins());
+ // Initialize trigonometric lookup tables and constants.
+ // The snapshot cannot contain typed arrays, and we don't need it to.
+ const int table_num_bytes = TrigonometricLookupTable::table_num_bytes();
+ v8::Local<v8::ArrayBuffer> sin_buffer = v8::ArrayBuffer::New(
+ TrigonometricLookupTable::sin_table(), table_num_bytes);
+ v8::Local<v8::ArrayBuffer> cos_buffer = v8::ArrayBuffer::New(
+ TrigonometricLookupTable::cos_x_interval_table(), table_num_bytes);
+ v8::Local<v8::Float64Array> sin_table = v8::Float64Array::New(
+ sin_buffer, 0, TrigonometricLookupTable::table_size());
+ v8::Local<v8::Float64Array> cos_table = v8::Float64Array::New(
+ cos_buffer, 0, TrigonometricLookupTable::table_size());
+
+ ForceSetProperty(builtins,
+ factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("kSinTable")),
+ Utils::OpenHandle(*sin_table),
+ NONE);
+ ForceSetProperty(builtins,
+ factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("kCosXIntervalTable")),
+ Utils::OpenHandle(*cos_table),
+ NONE);
+ ForceSetProperty(builtins,
+ factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("kSamples")),
+ factory()->NewHeapNumber(
+ TrigonometricLookupTable::samples()),
+ NONE);
+ ForceSetProperty(builtins,
+ factory()->InternalizeOneByteString(
+ STATIC_ASCII_VECTOR("kIndexConvert")),
+ factory()->NewHeapNumber(
+ TrigonometricLookupTable::samples_over_pi_half()),
+ NONE);
+ }
+
// Initially seed the per-context random number generator
// using the per-isolate random number generator.
uint32_t* state = reinterpret_cast<uint32_t*>(
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 62e19e1..3d42483 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -511,6 +511,22 @@
AllocationSite::kNestedSiteOffset),
graph()->GetConstant0());
+ // Pretenuring calculation fields.
+ Add<HStoreNamedField>(object,
+ HObjectAccess::ForAllocationSiteOffset(
+ AllocationSite::kMementoFoundCountOffset),
+ graph()->GetConstant0());
+
+ Add<HStoreNamedField>(object,
+ HObjectAccess::ForAllocationSiteOffset(
+ AllocationSite::kMementoCreateCountOffset),
+ graph()->GetConstant0());
+
+ Add<HStoreNamedField>(object,
+ HObjectAccess::ForAllocationSiteOffset(
+ AllocationSite::kPretenureDecisionOffset),
+ graph()->GetConstant0());
+
// Store an empty fixed array for the code dependency.
HConstant* empty_fixed_array =
Add<HConstant>(isolate()->factory()->empty_fixed_array());
@@ -992,16 +1008,10 @@
// Make sure that both arguments are strings if not known in advance.
if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
- IfBuilder if_leftnotstring(this);
- if_leftnotstring.IfNot<HIsStringAndBranch>(left);
- if_leftnotstring.Then();
- if_leftnotstring.Deopt("Expected string for LHS of string addition");
+ left = BuildCheckString(left);
}
if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
- IfBuilder if_rightnotstring(this);
- if_rightnotstring.IfNot<HIsStringAndBranch>(right);
- if_rightnotstring.Then();
- if_rightnotstring.Deopt("Expected string for RHS of string addition");
+ right = BuildCheckString(right);
}
return BuildStringAdd(left, right, pretenure_flag);
diff --git a/src/d8.cc b/src/d8.cc
index 5b128c0..41b08bc 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1379,43 +1379,6 @@
} else if (strcmp(argv[i], "--send-idle-notification") == 0) {
options.send_idle_notification = true;
argv[i] = NULL;
- } else if (strcmp(argv[i], "--preemption") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
- return false;
-#else
- options.use_preemption = true;
- argv[i] = NULL;
-#endif // V8_SHARED
- } else if (strcmp(argv[i], "--nopreemption") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
- return false;
-#else
- options.use_preemption = false;
- argv[i] = NULL;
-#endif // V8_SHARED
- } else if (strcmp(argv[i], "--preemption-interval") == 0) {
-#ifdef V8_SHARED
- printf("D8 with shared library does not support multi-threading\n");
- return false;
-#else
- if (++i < argc) {
- argv[i-1] = NULL;
- char* end = NULL;
- options.preemption_interval = strtol(argv[i], &end, 10); // NOLINT
- if (options.preemption_interval <= 0
- || *end != '\0'
- || errno == ERANGE) {
- printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
- return false;
- }
- argv[i] = NULL;
- } else {
- printf("Missing value for --preemption-interval\n");
- return false;
- }
-#endif // V8_SHARED
} else if (strcmp(argv[i], "-f") == 0) {
// Ignore any -f flags for compatibility with other stand-alone
// JavaScript engines.
@@ -1554,14 +1517,6 @@
V8::IdleNotification(kLongIdlePauseInMs);
}
}
-
-#ifndef V8_SHARED
- // Start preemption if threads have been created and preemption is enabled.
- if (threads.length() > 0
- && options.use_preemption) {
- Locker::StartPreemption(isolate, options.preemption_interval);
- }
-#endif // V8_SHARED
}
#ifndef V8_SHARED
@@ -1574,11 +1529,6 @@
thread->Join();
delete thread;
}
-
- if (threads.length() > 0 && options.use_preemption) {
- Locker lock(isolate);
- Locker::StopPreemption(isolate);
- }
#endif // V8_SHARED
return 0;
}
diff --git a/src/d8.h b/src/d8.h
index 8c1687e..761276e 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -219,8 +219,6 @@
public:
ShellOptions() :
#ifndef V8_SHARED
- use_preemption(true),
- preemption_interval(10),
num_parallel_files(0),
parallel_files(NULL),
#endif // V8_SHARED
@@ -245,8 +243,6 @@
}
#ifndef V8_SHARED
- bool use_preemption;
- int preemption_interval;
int num_parallel_files;
char** parallel_files;
#endif // V8_SHARED
diff --git a/src/default-platform.cc b/src/default-platform.cc
new file mode 100644
index 0000000..ef3c4eb
--- /dev/null
+++ b/src/default-platform.cc
@@ -0,0 +1,56 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "default-platform.h"
+
+namespace v8 {
+namespace internal {
+
+
+DefaultPlatform::DefaultPlatform() {}
+
+
+DefaultPlatform::~DefaultPlatform() {}
+
+void DefaultPlatform::CallOnBackgroundThread(Task *task,
+ ExpectedRuntime expected_runtime) {
+ // TODO(jochen): implement.
+ task->Run();
+ delete task;
+}
+
+
+void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
+ // TODO(jochen): implement.
+ task->Run();
+ delete task;
+}
+
+
+} } // namespace v8::internal
diff --git a/src/default-platform.h b/src/default-platform.h
new file mode 100644
index 0000000..fe1bf8e
--- /dev/null
+++ b/src/default-platform.h
@@ -0,0 +1,55 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_DEFAULT_PLATFORM_H_
+#define V8_DEFAULT_PLATFORM_H_
+
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+class DefaultPlatform : public Platform {
+ public:
+ DefaultPlatform();
+ virtual ~DefaultPlatform();
+
+ // v8::Platform implementation.
+ virtual void CallOnBackgroundThread(
+ Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
+ virtual void CallOnForegroundThread(v8::Isolate *isolate,
+ Task *task) V8_OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
+};
+
+
+} } // namespace v8::internal
+
+
+#endif // V8_DEFAULT_PLATFORM_H_
diff --git a/src/execution.cc b/src/execution.cc
index 8febbbf..32c616f 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -814,8 +814,6 @@
// Clear the preempt request flag.
isolate->stack_guard()->Continue(PREEMPT);
- ContextSwitcher::PreemptionReceived();
-
#ifdef ENABLE_DEBUGGER_SUPPORT
if (isolate->debug()->InDebugger()) {
// If currently in the debugger don't do any actual preemption but record
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 62cb307..1c95885 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -611,10 +611,6 @@
DEFINE_bool(profile_deserialization, false,
"Print the time it takes to deserialize the snapshot.")
-// v8.cc
-DEFINE_bool(preemption, false,
- "activate a 100ms timer that switches between V8 threads")
-
// Regexp
DEFINE_bool(regexp_optimization, true, "generate optimized regexp code")
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index b7b7f22..7e74d86 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1526,6 +1526,15 @@
AllocationSite::kTransitionInfoOffset);
SetInternalReference(site, entry, "nested_site", site->nested_site(),
AllocationSite::kNestedSiteOffset);
+ SetInternalReference(site, entry, "memento_found_count",
+ site->memento_found_count(),
+ AllocationSite::kMementoFoundCountOffset);
+ SetInternalReference(site, entry, "memento_create_count",
+ site->memento_create_count(),
+ AllocationSite::kMementoCreateCountOffset);
+ SetInternalReference(site, entry, "pretenure_decision",
+ site->pretenure_decision(),
+ AllocationSite::kPretenureDecisionOffset);
SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
AllocationSite::kDependentCodeOffset);
}
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index f7b3100..fd93ce3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1273,17 +1273,14 @@
}
-HValue* HGraphBuilder::BuildCheckString(
- HValue* object, const char* failure_reason) {
- if (!object->type().IsString()) {
- ASSERT(!object->IsConstant() ||
- !HConstant::cast(object)->HasStringValue());
- IfBuilder if_isstring(this);
- if_isstring.If<HIsStringAndBranch>(object);
- if_isstring.Then();
- if_isstring.ElseDeopt(failure_reason);
+HValue* HGraphBuilder::BuildCheckString(HValue* string) {
+ if (!string->type().IsString()) {
+ ASSERT(!string->IsConstant() ||
+ !HConstant::cast(string)->HasStringValue());
+ BuildCheckHeapObject(string);
+ return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
}
- return object;
+ return string;
}
@@ -8657,14 +8654,12 @@
(left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
// Validate type feedback for left argument.
if (left_type->Is(Type::String())) {
- left = BuildCheckString(
- left, "Expected string for LHS of binary operation");
+ left = BuildCheckString(left);
}
// Validate type feedback for right argument.
if (right_type->Is(Type::String())) {
- right = BuildCheckString(
- right, "Expected string for RHS of binary operation");
+ right = BuildCheckString(right);
}
// Convert left argument as necessary.
diff --git a/src/hydrogen.h b/src/hydrogen.h
index a117c55..d11fbc0 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1256,7 +1256,7 @@
HValue* BuildCheckHeapObject(HValue* object);
HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
- HValue* BuildCheckString(HValue* object, const char* failure_reason);
+ HValue* BuildCheckString(HValue* string);
HValue* BuildWrapReceiver(HValue* object, HValue* function);
// Building common constructs
diff --git a/src/isolate.cc b/src/isolate.cc
index 7250246..2acc59a 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1549,7 +1549,6 @@
write_iterator_(NULL),
global_handles_(NULL),
eternal_handles_(NULL),
- context_switcher_(NULL),
thread_manager_(NULL),
fp_stubs_generated_(false),
has_installed_extensions_(false),
@@ -1690,10 +1689,6 @@
delete deoptimizer_data_;
deoptimizer_data_ = NULL;
- if (FLAG_preemption) {
- v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
- v8::Locker::StopPreemption(reinterpret_cast<v8::Isolate*>(this));
- }
builtins_.TearDown();
bootstrapper_->TearDown();
@@ -1805,8 +1800,6 @@
delete write_iterator_;
write_iterator_ = NULL;
- delete context_switcher_;
- context_switcher_ = NULL;
delete thread_manager_;
thread_manager_ = NULL;
@@ -2038,11 +2031,6 @@
}
}
- if (FLAG_preemption) {
- v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
- v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100);
- }
-
#ifdef ENABLE_DEBUGGER_SUPPORT
debug_->SetUp(create_heap_objects);
#endif
diff --git a/src/isolate.h b/src/isolate.h
index ed568b7..f280ee8 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -58,7 +58,6 @@
class CodeTracer;
class CompilationCache;
class ContextSlotCache;
-class ContextSwitcher;
class Counters;
class CpuFeatures;
class CpuProfiler;
@@ -919,12 +918,6 @@
ThreadManager* thread_manager() { return thread_manager_; }
- ContextSwitcher* context_switcher() { return context_switcher_; }
-
- void set_context_switcher(ContextSwitcher* switcher) {
- context_switcher_ = switcher;
- }
-
StringTracker* string_tracker() { return string_tracker_; }
unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
@@ -1293,7 +1286,6 @@
ConsStringIteratorOp* write_iterator_;
GlobalHandles* global_handles_;
EternalHandles* eternal_handles_;
- ContextSwitcher* context_switcher_;
ThreadManager* thread_manager_;
RuntimeState runtime_state_;
bool fp_stubs_generated_;
diff --git a/src/math.js b/src/math.js
index 2df0ec2..c163d9a 100644
--- a/src/math.js
+++ b/src/math.js
@@ -79,7 +79,8 @@
// ECMA 262 - 15.8.2.7
function MathCos(x) {
- return MathCosImpl(x);
+ x = MathAbs(x); // Convert to number and get rid of -0.
+ return TrigonometricInterpolation(x, 1);
}
// ECMA 262 - 15.8.2.8
@@ -179,7 +180,9 @@
// ECMA 262 - 15.8.2.16
function MathSin(x) {
- return MathSinImpl(x);
+ x = x * 1; // Convert to number and deal with -0.
+ if (%_IsMinusZero(x)) return x;
+ return TrigonometricInterpolation(x, 0);
}
// ECMA 262 - 15.8.2.17
@@ -189,7 +192,7 @@
// ECMA 262 - 15.8.2.18
function MathTan(x) {
- return MathSinImpl(x) / MathCosImpl(x);
+ return MathSin(x) / MathCos(x);
}
// Non-standard extension.
@@ -198,119 +201,73 @@
}
-var MathSinImpl = function(x) {
- InitTrigonometricFunctions();
- return MathSinImpl(x);
-}
+var kInversePiHalf = 0.636619772367581343; // 2 / pi
+var kInversePiHalfS26 = 9.48637384723993156e-9; // 2 / pi / (2^26)
+var kS26 = 1 << 26;
+var kTwoStepThreshold = 1 << 27;
+// pi / 2 rounded up
+var kPiHalf = 1.570796326794896780; // 0x192d4454fb21f93f
+// We use two parts for pi/2 to emulate a higher precision.
+// pi_half_1 only has 26 significant bits for mantissa.
+// Note that pi_half > pi_half_1 + pi_half_2
+var kPiHalf1 = 1.570796325802803040; // 0x00000054fb21f93f
+var kPiHalf2 = 9.920935796805404252e-10; // 0x3326a611460b113e
+var kSamples; // Initialized to a number during genesis.
+var kIndexConvert; // Initialized to kSamples / (pi/2) during genesis.
+var kSinTable; // Initialized to a Float64Array during genesis.
+var kCosXIntervalTable; // Initialized to a Float64Array during genesis.
-var MathCosImpl = function(x) {
- InitTrigonometricFunctions();
- return MathCosImpl(x);
-}
-
-
-var InitTrigonometricFunctions;
-
-
-// Define constants and interpolation functions.
-// Also define the initialization function that populates the lookup table
-// and then wires up the function definitions.
-function SetupTrigonometricFunctions() {
- var samples = 1800; // Table size. Do not change arbitrarily.
- var inverse_pi_half = 0.636619772367581343; // 2 / pi
- var inverse_pi_half_s_26 = 9.48637384723993156e-9; // 2 / pi / (2^26)
- var s_26 = 1 << 26;
- var two_step_threshold = 1 << 27;
- var index_convert = 1145.915590261646418; // samples / (pi / 2)
- // pi / 2 rounded up
- var pi_half = 1.570796326794896780; // 0x192d4454fb21f93f
- // We use two parts for pi/2 to emulate a higher precision.
- // pi_half_1 only has 26 significant bits for mantissa.
- // Note that pi_half > pi_half_1 + pi_half_2
- var pi_half_1 = 1.570796325802803040; // 0x00000054fb21f93f
- var pi_half_2 = 9.920935796805404252e-10; // 0x3326a611460b113e
- var table_sin;
- var table_cos_interval;
-
- // This implements sine using the following algorithm.
- // 1) Multiplication takes care of to-number conversion.
- // 2) Reduce x to the first quadrant [0, pi/2].
- // Conveniently enough, in case of +/-Infinity, we get NaN.
- // Note that we try to use only 26 instead of 52 significant bits for
- // mantissa to avoid rounding errors when multiplying. For very large
- // input we therefore have additional steps.
- // 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant.
- // 4) Do a table lookup for the closest samples to the left and right of x.
- // 5) Find the derivatives at those sampling points by table lookup:
- // dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2].
- // 6) Use cubic spline interpolation to approximate sin(x).
- // 7) Negate the result if x was in the 3rd or 4th quadrant.
- // 8) Get rid of -0 by adding 0.
- var Interpolation = function(x, phase) {
- if (x < 0 || x > pi_half) {
- var multiple;
- while (x < -two_step_threshold || x > two_step_threshold) {
- // Let's assume this loop does not terminate.
- // All numbers x in each loop forms a set S.
- // (1) abs(x) > 2^27 for all x in S.
- // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1
- // (3) multiple is rounded down in 2^26 steps, so the rounding error is
- // at most max(ulp, 2^26).
- // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least
- // (1-pi/4)x
- // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4.
- // Note that this difference cannot be simply rounded off.
- // Set S cannot exist since (5) violates (1). Loop must terminate.
- multiple = MathFloor(x * inverse_pi_half_s_26) * s_26;
- x = x - multiple * pi_half_1 - multiple * pi_half_2;
- }
- multiple = MathFloor(x * inverse_pi_half);
- x = x - multiple * pi_half_1 - multiple * pi_half_2;
- phase += multiple;
+// This implements sine using the following algorithm.
+// 1) Multiplication takes care of to-number conversion.
+// 2) Reduce x to the first quadrant [0, pi/2].
+// Conveniently enough, in case of +/-Infinity, we get NaN.
+// Note that we try to use only 26 instead of 52 significant bits for
+// mantissa to avoid rounding errors when multiplying. For very large
+// input we therefore have additional steps.
+// 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant.
+// 4) Do a table lookup for the closest samples to the left and right of x.
+// 5) Find the derivatives at those sampling points by table lookup:
+// dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2].
+// 6) Use cubic spline interpolation to approximate sin(x).
+// 7) Negate the result if x was in the 3rd or 4th quadrant.
+// 8) Get rid of -0 by adding 0.
+function TrigonometricInterpolation(x, phase) {
+ if (x < 0 || x > kPiHalf) {
+ var multiple;
+ while (x < -kTwoStepThreshold || x > kTwoStepThreshold) {
+ // Let's assume this loop does not terminate.
+ // All numbers x in each loop forms a set S.
+ // (1) abs(x) > 2^27 for all x in S.
+ // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1
+ // (3) multiple is rounded down in 2^26 steps, so the rounding error is
+ // at most max(ulp, 2^26).
+ // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least
+ // (1-pi/4)x
+ // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4.
+ // Note that this difference cannot be simply rounded off.
+ // Set S cannot exist since (5) violates (1). Loop must terminate.
+ multiple = MathFloor(x * kInversePiHalfS26) * kS26;
+ x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
}
- var double_index = x * index_convert;
- if (phase & 1) double_index = samples - double_index;
- var index = double_index | 0;
- var t1 = double_index - index;
- var t2 = 1 - t1;
- var y1 = table_sin[index];
- var y2 = table_sin[index + 1];
- var dy = y2 - y1;
- return (t2 * y1 + t1 * y2 +
- t1 * t2 * ((table_cos_interval[index] - dy) * t2 +
- (dy - table_cos_interval[index + 1]) * t1))
- * (1 - (phase & 2)) + 0;
+ multiple = MathFloor(x * kInversePiHalf);
+ x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
+ phase += multiple;
}
-
- var MathSinInterpolation = function(x) {
- x = x * 1; // Convert to number and deal with -0.
- if (%_IsMinusZero(x)) return x;
- return Interpolation(x, 0);
- }
-
- // Cosine is sine with a phase offset.
- var MathCosInterpolation = function(x) {
- x = MathAbs(x); // Convert to number and get rid of -0.
- return Interpolation(x, 1);
- };
-
- %SetInlineBuiltinFlag(Interpolation);
- %SetInlineBuiltinFlag(MathSinInterpolation);
- %SetInlineBuiltinFlag(MathCosInterpolation);
-
- InitTrigonometricFunctions = function() {
- table_sin = new global.Float64Array(samples + 2);
- table_cos_interval = new global.Float64Array(samples + 2);
- %PopulateTrigonometricTable(table_sin, table_cos_interval, samples);
- MathSinImpl = MathSinInterpolation;
- MathCosImpl = MathCosInterpolation;
- }
+ var double_index = x * kIndexConvert;
+ if (phase & 1) double_index = kSamples - double_index;
+ var index = double_index | 0;
+ var t1 = double_index - index;
+ var t2 = 1 - t1;
+ var y1 = kSinTable[index];
+ var y2 = kSinTable[index + 1];
+ var dy = y2 - y1;
+ return (t2 * y1 + t1 * y2 +
+ t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 +
+ (dy - kCosXIntervalTable[index + 1]) * t1))
+ * (1 - (phase & 2)) + 0;
}
-SetupTrigonometricFunctions();
-
-
// -------------------------------------------------------------------
function SetUpMath() {
@@ -387,6 +344,7 @@
%SetInlineBuiltinFlag(MathSin);
%SetInlineBuiltinFlag(MathCos);
%SetInlineBuiltinFlag(MathTan);
+ %SetInlineBuiltinFlag(TrigonometricInterpolation);
}
SetUpMath();
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index bc5d62a..43d83bd 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -3037,22 +3037,44 @@
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
Register arguments = ToRegister(instr->arguments());
Register result = ToRegister(instr->result());
- if (instr->length()->IsConstantOperand() &&
- instr->index()->IsConstantOperand()) {
- int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ // There are two words between the frame pointer and the last argument.
+ // Subtracting from length accounts for one of them add one more.
+ if (instr->length()->IsConstantOperand()) {
int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
- int index = (const_length - const_index) + 1;
- __ lw(result, MemOperand(arguments, index * kPointerSize));
+ if (instr->index()->IsConstantOperand()) {
+ int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int index = (const_length - const_index) + 1;
+ __ lw(result, MemOperand(arguments, index * kPointerSize));
+ } else {
+ Register index = ToRegister(instr->index());
+ __ li(at, Operand(const_length + 1));
+ __ Subu(result, at, index);
+ __ sll(at, result, kPointerSizeLog2);
+ __ Addu(at, arguments, at);
+ __ lw(result, MemOperand(at));
+ }
+ } else if (instr->index()->IsConstantOperand()) {
+ Register length = ToRegister(instr->length());
+ int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+ int loc = const_index - 1;
+ if (loc != 0) {
+ __ Subu(result, length, Operand(loc));
+ __ sll(at, result, kPointerSizeLog2);
+ __ Addu(at, arguments, at);
+ __ lw(result, MemOperand(at));
+ } else {
+ __ sll(at, length, kPointerSizeLog2);
+ __ Addu(at, arguments, at);
+ __ lw(result, MemOperand(at));
+ }
} else {
Register length = ToRegister(instr->length());
Register index = ToRegister(instr->index());
- // There are two words between the frame pointer and the last argument.
- // Subtracting from length accounts for one of them, add one more.
- __ subu(length, length, index);
- __ Addu(length, length, Operand(1));
- __ sll(length, length, kPointerSizeLog2);
- __ Addu(at, arguments, Operand(length));
- __ lw(result, MemOperand(at, 0));
+ __ Subu(result, length, index);
+ __ Addu(result, result, 1);
+ __ sll(at, result, kPointerSizeLog2);
+ __ Addu(at, arguments, at);
+ __ lw(result, MemOperand(at));
}
}
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index abdc3e6..5dbef8d 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -2472,15 +2472,8 @@
LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
info()->MarkAsRequiresFrame();
LOperand* args = UseRegister(instr->arguments());
- LOperand* length;
- LOperand* index;
- if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
- length = UseRegisterOrConstant(instr->length());
- index = UseOrConstant(instr->index());
- } else {
- length = UseTempRegister(instr->length());
- index = UseRegisterAtStart(instr->index());
- }
+ LOperand* length = UseRegisterOrConstantAtStart(instr->length());
+ LOperand* index = UseRegisterOrConstantAtStart(instr->index());
return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 2e8c0ad..7064ea9 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1314,6 +1314,9 @@
set_transition_info(Smi::FromInt(0));
SetElementsKind(GetInitialFastElementsKind());
set_nested_site(Smi::FromInt(0));
+ set_memento_create_count(Smi::FromInt(0));
+ set_memento_found_count(Smi::FromInt(0));
+ set_pretenure_decision(Smi::FromInt(0));
set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
SKIP_WRITE_BARRIER);
}
@@ -3874,33 +3877,14 @@
int Code::major_key() {
- ASSERT(kind() == STUB ||
- kind() == HANDLER ||
- kind() == BINARY_OP_IC ||
- kind() == COMPARE_IC ||
- kind() == COMPARE_NIL_IC ||
- kind() == STORE_IC ||
- kind() == LOAD_IC ||
- kind() == KEYED_LOAD_IC ||
- kind() == KEYED_CALL_IC ||
- kind() == TO_BOOLEAN_IC);
+ ASSERT(has_major_key());
return StubMajorKeyField::decode(
READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
}
void Code::set_major_key(int major) {
- ASSERT(kind() == STUB ||
- kind() == HANDLER ||
- kind() == BINARY_OP_IC ||
- kind() == COMPARE_IC ||
- kind() == COMPARE_NIL_IC ||
- kind() == LOAD_IC ||
- kind() == KEYED_LOAD_IC ||
- kind() == STORE_IC ||
- kind() == KEYED_STORE_IC ||
- kind() == KEYED_CALL_IC ||
- kind() == TO_BOOLEAN_IC);
+ ASSERT(has_major_key());
ASSERT(0 <= major && major < 256);
int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
int updated = StubMajorKeyField::update(previous, major);
@@ -3908,6 +3892,21 @@
}
+bool Code::has_major_key() {
+ return kind() == STUB ||
+ kind() == HANDLER ||
+ kind() == BINARY_OP_IC ||
+ kind() == COMPARE_IC ||
+ kind() == COMPARE_NIL_IC ||
+ kind() == LOAD_IC ||
+ kind() == KEYED_LOAD_IC ||
+ kind() == STORE_IC ||
+ kind() == KEYED_STORE_IC ||
+ kind() == KEYED_CALL_IC ||
+ kind() == TO_BOOLEAN_IC;
+}
+
+
bool Code::is_pregenerated() {
return (kind() == STUB && IsPregeneratedField::decode(flags()));
}
@@ -4552,6 +4551,10 @@
ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
+ACCESSORS_TO_SMI(AllocationSite, memento_found_count, kMementoFoundCountOffset)
+ACCESSORS_TO_SMI(AllocationSite, memento_create_count,
+ kMementoCreateCountOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_decision, kPretenureDecisionOffset)
ACCESSORS(AllocationSite, dependent_code, DependentCode,
kDependentCodeOffset)
ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 5260193..9f1b939 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -1125,6 +1125,12 @@
dependent_code()->ShortPrint(out);
PrintF(out, "\n - nested site: ");
nested_site()->ShortPrint(out);
+ PrintF(out, "\n - memento found count: ");
+ memento_found_count()->ShortPrint(out);
+ PrintF(out, "\n - memento create count: ");
+ memento_create_count()->ShortPrint(out);
+ PrintF(out, "\n - pretenure decision: ");
+ pretenure_decision()->ShortPrint(out);
PrintF(out, "\n - transition_info: ");
if (transition_info()->IsSmi()) {
ElementsKind kind = GetElementsKind();
diff --git a/src/objects.cc b/src/objects.cc
index c874ee3..2b38b1d 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -33,6 +33,7 @@
#include "arguments.h"
#include "bootstrapper.h"
#include "codegen.h"
+#include "code-stubs.h"
#include "cpu-profiler.h"
#include "debug.h"
#include "deoptimizer.h"
@@ -11135,6 +11136,10 @@
void Code::Disassemble(const char* name, FILE* out) {
PrintF(out, "kind = %s\n", Kind2String(kind()));
+ if (has_major_key()) {
+ PrintF(out, "major_key = %s\n",
+ CodeStub::MajorName(CodeStub::GetMajorKey(this), true));
+ }
if (is_inline_cache_stub()) {
PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
PrintExtraICState(out, kind(), needs_extended_extra_ic_state(kind()) ?
diff --git a/src/objects.h b/src/objects.h
index 352edaa..cf4c80b 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5141,6 +5141,7 @@
// [major_key]: For kind STUB or BINARY_OP_IC, the major key.
inline int major_key();
inline void set_major_key(int value);
+ inline bool has_major_key();
// For kind STUB or ICs, tells whether or not a code object was generated by
// the optimizing compiler (but it may not be an optimized function).
@@ -8110,6 +8111,9 @@
// walked in a particular order. So [[1, 2], 1, 2] will have one
// nested_site, but [[1, 2], 3, [4]] will have a list of two.
DECL_ACCESSORS(nested_site, Object)
+ DECL_ACCESSORS(memento_found_count, Smi)
+ DECL_ACCESSORS(memento_create_count, Smi)
+ DECL_ACCESSORS(pretenure_decision, Smi)
DECL_ACCESSORS(dependent_code, DependentCode)
DECL_ACCESSORS(weak_next, Object)
@@ -8177,7 +8181,13 @@
static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
- static const int kDependentCodeOffset = kNestedSiteOffset + kPointerSize;
+ static const int kMementoFoundCountOffset = kNestedSiteOffset + kPointerSize;
+ static const int kMementoCreateCountOffset =
+ kMementoFoundCountOffset + kPointerSize;
+ static const int kPretenureDecisionOffset =
+ kMementoCreateCountOffset + kPointerSize;
+ static const int kDependentCodeOffset =
+ kPretenureDecisionOffset + kPointerSize;
static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
static const int kSize = kWeakNextOffset + kPointerSize;
diff --git a/src/runtime.cc b/src/runtime.cc
index f546629..c11a005 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -7848,35 +7848,6 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PopulateTrigonometricTable) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sin_table, 0);
- CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, cos_table, 1);
- CONVERT_SMI_ARG_CHECKED(samples, 2);
- RUNTIME_ASSERT(sin_table->type() == kExternalDoubleArray);
- RUNTIME_ASSERT(cos_table->type() == kExternalDoubleArray);
- double* sin_buffer = reinterpret_cast<double*>(
- JSArrayBuffer::cast(sin_table->buffer())->backing_store());
- double* cos_buffer = reinterpret_cast<double*>(
- JSArrayBuffer::cast(cos_table->buffer())->backing_store());
-
- static const double pi_half = 3.1415926535897932 / 2;
- double interval = pi_half / samples;
- for (int i = 0; i < samples + 1; i++) {
- double sample = sin(i * interval);
- sin_buffer[i] = sample;
- cos_buffer[samples - i] = sample * interval;
- }
-
- // Fill this to catch out of bound accesses when calculating Math.sin(pi/2).
- sin_buffer[samples + 1] = sin(pi_half + interval);
- cos_buffer[samples + 1] = cos(pi_half + interval) * interval;
-
- return isolate->heap()->undefined_value();
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
diff --git a/src/runtime.h b/src/runtime.h
index 4872ab5..0e09200 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -190,7 +190,6 @@
F(Math_sin, 1, 1) \
F(Math_sqrt, 1, 1) \
F(Math_tan, 1, 1) \
- F(PopulateTrigonometricTable, 3, 1) \
\
/* Regular expressions */ \
F(RegExpCompile, 3, 1) \
diff --git a/src/trig-table.h b/src/trig-table.h
new file mode 100644
index 0000000..081c038
--- /dev/null
+++ b/src/trig-table.h
@@ -0,0 +1,61 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_TRIG_TABLE_H_
+#define V8_TRIG_TABLE_H_
+
+
+namespace v8 {
+namespace internal {
+
+class TrigonometricLookupTable : public AllStatic {
+ public:
+ // Casting away const-ness to use as argument for typed array constructor.
+ static void* sin_table() {
+ return const_cast<double*>(&kSinTable[0]);
+ }
+
+ static void* cos_x_interval_table() {
+ return const_cast<double*>(&kCosXIntervalTable[0]);
+ }
+
+ static double samples_over_pi_half() { return kSamplesOverPiHalf; }
+ static int samples() { return kSamples; }
+ static int table_num_bytes() { return kTableSize * sizeof(*kSinTable); }
+ static int table_size() { return kTableSize; }
+
+ private:
+ static const double kSinTable[];
+ static const double kCosXIntervalTable[];
+ static const int kSamples;
+ static const int kTableSize;
+ static const double kSamplesOverPiHalf;
+};
+
+} } // namespace v8::internal
+
+#endif // V8_TRIG_TABLE_H_
diff --git a/src/v8.cc b/src/v8.cc
index 17007a2..c56c82a 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -32,6 +32,9 @@
#include "elements.h"
#include "bootstrapper.h"
#include "debug.h"
+#ifdef V8_USE_DEFAULT_PLATFORM
+#include "default-platform.h"
+#endif
#include "deoptimizer.h"
#include "frames.h"
#include "heap-profiler.h"
@@ -52,6 +55,7 @@
List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL;
v8::ArrayBuffer::Allocator* V8::array_buffer_allocator_ = NULL;
+v8::Platform* V8::platform_ = NULL;
bool V8::Initialize(Deserializer* des) {
@@ -100,6 +104,12 @@
call_completed_callbacks_ = NULL;
Sampler::TearDown();
+
+#ifdef V8_USE_DEFAULT_PLATFORM
+ DefaultPlatform* platform = static_cast<DefaultPlatform*>(platform_);
+ platform_ = NULL;
+ delete platform;
+#endif
}
@@ -179,6 +189,9 @@
FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
}
+#ifdef V8_USE_DEFAULT_PLATFORM
+ platform_ = new DefaultPlatform;
+#endif
Sampler::SetUp();
CPU::SetUp();
OS::PostSetUp();
@@ -194,4 +207,23 @@
CallOnce(&init_once, &InitializeOncePerProcessImpl);
}
+
+void V8::InitializePlatform(v8::Platform* platform) {
+ ASSERT(!platform_);
+ ASSERT(platform);
+ platform_ = platform;
+}
+
+
+void V8::ShutdownPlatform() {
+ ASSERT(platform_);
+ platform_ = NULL;
+}
+
+
+v8::Platform* V8::GetCurrentPlatform() {
+ ASSERT(platform_);
+ return platform_;
+}
+
} } // namespace v8::internal
diff --git a/src/v8.h b/src/v8.h
index 01362ab..6f2633a 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -50,6 +50,7 @@
// Basic includes
#include "../include/v8.h"
+#include "../include/v8-platform.h"
#include "v8globals.h"
#include "v8checks.h"
#include "allocation.h"
@@ -111,6 +112,10 @@
array_buffer_allocator_ = allocator;
}
+ static void InitializePlatform(v8::Platform* platform);
+ static void ShutdownPlatform();
+ static v8::Platform* GetCurrentPlatform();
+
private:
static void InitializeOncePerProcessImpl();
static void InitializeOncePerProcess();
@@ -119,6 +124,8 @@
static List<CallCompletedCallback>* call_completed_callbacks_;
// Allocator for external array buffers.
static v8::ArrayBuffer::Allocator* array_buffer_allocator_;
+ // v8::Platform to use.
+ static v8::Platform* platform_;
};
diff --git a/src/v8threads.cc b/src/v8threads.cc
index cc4f439..1de9d4f 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -133,18 +133,6 @@
}
-void Locker::StartPreemption(v8::Isolate* isolate, int every_n_ms) {
- v8::internal::ContextSwitcher::StartPreemption(
- reinterpret_cast<i::Isolate*>(isolate), every_n_ms);
-}
-
-
-void Locker::StopPreemption(v8::Isolate* isolate) {
- v8::internal::ContextSwitcher::StopPreemption(
- reinterpret_cast<i::Isolate*>(isolate));
-}
-
-
namespace internal {
@@ -419,63 +407,5 @@
}
-ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
- : Thread("v8:CtxtSwitcher"),
- keep_going_(true),
- sleep_ms_(every_n_ms),
- isolate_(isolate) {
-}
-
-
-// Set the scheduling interval of V8 threads. This function starts the
-// ContextSwitcher thread if needed.
-void ContextSwitcher::StartPreemption(Isolate* isolate, int every_n_ms) {
- ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
- if (isolate->context_switcher() == NULL) {
- // If the ContextSwitcher thread is not running at the moment start it now.
- isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
- isolate->context_switcher()->Start();
- } else {
- // ContextSwitcher thread is already running, so we just change the
- // scheduling interval.
- isolate->context_switcher()->sleep_ms_ = every_n_ms;
- }
-}
-
-
-// Disable preemption of V8 threads. If multiple threads want to use V8 they
-// must cooperatively schedule amongst them from this point on.
-void ContextSwitcher::StopPreemption(Isolate* isolate) {
- ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
- if (isolate->context_switcher() != NULL) {
- // The ContextSwitcher thread is running. We need to stop it and release
- // its resources.
- isolate->context_switcher()->keep_going_ = false;
- // Wait for the ContextSwitcher thread to exit.
- isolate->context_switcher()->Join();
- // Thread has exited, now we can delete it.
- delete(isolate->context_switcher());
- isolate->set_context_switcher(NULL);
- }
-}
-
-
-// Main loop of the ContextSwitcher thread: Preempt the currently running V8
-// thread at regular intervals.
-void ContextSwitcher::Run() {
- while (keep_going_) {
- OS::Sleep(sleep_ms_);
- isolate()->stack_guard()->Preempt();
- }
-}
-
-
-// Acknowledge the preemption by the receiving thread.
-void ContextSwitcher::PreemptionReceived() {
- // There is currently no accounting being done for this. But could be in the
- // future, which is why we leave this in.
-}
-
-
} // namespace internal
} // namespace v8
diff --git a/src/v8threads.h b/src/v8threads.h
index 1edacfc..a20700a 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -139,34 +139,6 @@
};
-// The ContextSwitcher thread is used to schedule regular preemptions to
-// multiple running V8 threads. Generally it is necessary to call
-// StartPreemption if there is more than one thread running. If not, a single
-// JavaScript can take full control of V8 and not allow other threads to run.
-class ContextSwitcher: public Thread {
- public:
- // Set the preemption interval for the ContextSwitcher thread.
- static void StartPreemption(Isolate* isolate, int every_n_ms);
-
- // Stop sending preemption requests to threads.
- static void StopPreemption(Isolate* isolate);
-
- // Preempted thread needs to call back to the ContextSwitcher to acknowledge
- // the handling of a preemption request.
- static void PreemptionReceived();
-
- private:
- ContextSwitcher(Isolate* isolate, int every_n_ms);
-
- Isolate* isolate() const { return isolate_; }
-
- void Run();
-
- bool keep_going_;
- int sleep_ms_;
- Isolate* isolate_;
-};
-
} } // namespace v8::internal
#endif // V8_V8THREADS_H_
diff --git a/src/version.cc b/src/version.cc
index 8ee0430..c76c1b2 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 23
-#define BUILD_NUMBER 9
+#define BUILD_NUMBER 10
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 2df0a89..761b402 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -14478,116 +14478,6 @@
}
-class ApplyInterruptTest {
- public:
- ApplyInterruptTest() : block_(0) {}
- ~ApplyInterruptTest() {}
- void RunTest() {
- gc_count_ = 0;
- gc_during_apply_ = 0;
- apply_success_ = false;
- gc_success_ = false;
- GCThread gc_thread(this);
- gc_thread.Start();
- v8::Isolate* isolate = CcTest::isolate();
- v8::Locker::StartPreemption(isolate, 1);
-
- LongRunningApply();
- {
- v8::Unlocker unlock(isolate);
- gc_thread.Join();
- }
- v8::Locker::StopPreemption(isolate);
- CHECK(apply_success_);
- CHECK(gc_success_);
- }
-
- private:
- // Number of garbage collections required.
- static const int kRequiredGCs = 2;
-
- class GCThread : public i::Thread {
- public:
- explicit GCThread(ApplyInterruptTest* test)
- : Thread("GCThread"), test_(test) {}
- virtual void Run() {
- test_->CollectGarbage();
- }
- private:
- ApplyInterruptTest* test_;
- };
-
- void CollectGarbage() {
- block_.Wait();
- while (gc_during_apply_ < kRequiredGCs) {
- {
- v8::Locker lock(CcTest::isolate());
- v8::Isolate::Scope isolate_scope(CcTest::isolate());
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- gc_count_++;
- }
- i::OS::Sleep(1);
- }
- gc_success_ = true;
- }
-
- void LongRunningApply() {
- block_.Signal();
- int rounds = 0;
- while (gc_during_apply_ < kRequiredGCs) {
- int gc_before = gc_count_;
- {
- const char* c_source =
- "function do_very_little(bar) {"
- " this.foo = bar;"
- "}"
- "for (var i = 0; i < 100000; i++) {"
- " do_very_little.apply(this, ['bar']);"
- "}";
- Local<String> source = String::New(c_source);
- Local<Script> script = Script::Compile(source);
- Local<Value> result = script->Run();
- // Check that no exception was thrown.
- CHECK(!result.IsEmpty());
- }
- int gc_after = gc_count_;
- gc_during_apply_ += gc_after - gc_before;
- rounds++;
- }
- apply_success_ = true;
- }
-
- i::Semaphore block_;
- int gc_count_;
- int gc_during_apply_;
- bool apply_success_;
- bool gc_success_;
-};
-
-
-// Test that nothing bad happens if we get a preemption just when we were
-// about to do an apply().
-TEST(ApplyInterruption) {
- v8::Locker lock(CcTest::isolate());
- v8::V8::Initialize();
- v8::HandleScope scope(CcTest::isolate());
- 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.
- ApplyInterruptTest().RunTest();
-
- local_env->Exit();
-}
-
-
// Verify that we can clone an object
TEST(ObjectClone) {
LocalContext env;
diff --git a/test/cctest/test-threads.cc b/test/cctest/test-threads.cc
index 4709961..c43c420 100644
--- a/test/cctest/test-threads.cc
+++ b/test/cctest/test-threads.cc
@@ -33,28 +33,6 @@
#include "cctest.h"
-TEST(Preemption) {
- v8::Isolate* isolate = CcTest::isolate();
- v8::Locker locker(isolate);
- v8::V8::Initialize();
- v8::HandleScope scope(isolate);
- v8::Handle<v8::Context> context = v8::Context::New(isolate);
- v8::Context::Scope context_scope(context);
-
- v8::Locker::StartPreemption(isolate, 100);
-
- v8::Handle<v8::Script> script = v8::Script::Compile(
- v8::String::New("var count = 0; var obj = new Object(); count++;\n"));
-
- script->Run();
-
- v8::Locker::StopPreemption(isolate);
- v8::internal::OS::Sleep(500); // Make sure the timer fires.
-
- script->Run();
-}
-
-
enum Turn {
FILL_CACHE,
CLEAN_CACHE,
diff --git a/test/cctest/test-weaktypedarrays.cc b/test/cctest/test-weaktypedarrays.cc
index fe1ef04..dc7dc75 100644
--- a/test/cctest/test-weaktypedarrays.cc
+++ b/test/cctest/test-weaktypedarrays.cc
@@ -89,7 +89,7 @@
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
- CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+ int start = CountArrayBuffersInWeakList(isolate->heap());
{
v8::HandleScope s1(context->GetIsolate());
v8::Handle<v8::ArrayBuffer> ab1 = v8::ArrayBuffer::New(256);
@@ -99,12 +99,12 @@
Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
Handle<JSArrayBuffer> iab2 = v8::Utils::OpenHandle(*ab2);
- CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start);
CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1));
CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab2));
}
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
{
HandleScope scope2(isolate);
Handle<JSArrayBuffer> iab1 = v8::Utils::OpenHandle(*ab1);
@@ -114,7 +114,7 @@
}
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap()));
}
@@ -122,11 +122,12 @@
v8::V8::Initialize();
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
+ int start = CountArrayBuffersInWeakList(isolate->heap());
for (int i = 1; i <= 3; i++) {
// Create 3 array buffers, make i-th of them garbage,
// validate correct state of array buffer weak list.
- CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap()));
{
v8::HandleScope scope(context->GetIsolate());
@@ -142,7 +143,7 @@
v8::Handle<v8::ArrayBuffer> ab3 =
v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab3"));
- CHECK_EQ(3, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(3, CountArrayBuffersInWeakList(isolate->heap()) - start);
CHECK(HasArrayBufferInWeakList(isolate->heap(),
*v8::Utils::OpenHandle(*ab1)));
CHECK(HasArrayBufferInWeakList(isolate->heap(),
@@ -156,7 +157,7 @@
CompileRun(source.start());
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start);
{
v8::HandleScope s2(context->GetIsolate());
@@ -174,7 +175,7 @@
}
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(0, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap()));
}
}
@@ -266,6 +267,7 @@
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
v8::HandleScope scope(context->GetIsolate());
+ int start = CountArrayBuffersInWeakList(isolate->heap());
CompileRun("var ab = new ArrayBuffer(2048);");
for (int i = 1; i <= 3; i++) {
// Create 3 typed arrays, make i-th of them garbage,
@@ -273,7 +275,7 @@
v8::HandleScope s0(context->GetIsolate());
i::ScopedVector<char> source(2048);
- CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
{
v8::HandleScope s1(context->GetIsolate());
@@ -292,7 +294,7 @@
v8::Handle<TypedArray>::Cast(CompileRun("ta2"));
v8::Handle<TypedArray> ta3 =
v8::Handle<TypedArray>::Cast(CompileRun("ta3"));
- CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
CHECK_EQ(3, CountViews(*iab));
CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta1)));
@@ -304,7 +306,7 @@
CompileRun(source.start());
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
{
v8::HandleScope s2(context->GetIsolate());
@@ -324,7 +326,7 @@
CompileRun("ta1 = null; ta2 = null; ta3 = null;");
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()));
+ CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
{
v8::HandleScope s3(context->GetIsolate());
diff --git a/tools/generate-trig-table.py b/tools/generate-trig-table.py
new file mode 100644
index 0000000..14d4472
--- /dev/null
+++ b/tools/generate-trig-table.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This is a utility for populating the lookup table for the
+# approximation of trigonometric functions.
+
+import sys, math
+
+SAMPLES = 1800
+
+TEMPLATE = """\
+// Copyright 2013 Google Inc. All Rights Reserved.
+
+// This file was generated from a python script.
+
+#include "v8.h"
+#include "trig-table.h"
+
+namespace v8 {
+namespace internal {
+
+ const double TrigonometricLookupTable::kSinTable[] =
+ { %(sine_table)s };
+ const double TrigonometricLookupTable::kCosXIntervalTable[] =
+ { %(cosine_table)s };
+ const int TrigonometricLookupTable::kSamples = %(samples)i;
+ const int TrigonometricLookupTable::kTableSize = %(table_size)i;
+ const double TrigonometricLookupTable::kSamplesOverPiHalf =
+ %(samples_over_pi_half)s;
+
+} } // v8::internal
+"""
+
+def main():
+ pi_half = math.pi / 2
+ interval = pi_half / SAMPLES
+ sin = []
+ cos_times_interval = []
+ table_size = SAMPLES + 2
+
+ for i in range(0, table_size):
+ sample = i * interval
+ sin.append(repr(math.sin(sample)))
+ cos_times_interval.append(repr(math.cos(sample) * interval))
+
+ output_file = sys.argv[1]
+ output = open(str(output_file), "w")
+ output.write(TEMPLATE % {
+ 'sine_table': ','.join(sin),
+ 'cosine_table': ','.join(cos_times_interval),
+ 'samples': SAMPLES,
+ 'table_size': table_size,
+ 'samples_over_pi_half': repr(SAMPLES / pi_half)
+ })
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index d5c33c6..65d5fb8 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -140,6 +140,7 @@
'sources': [
'<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
'<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc',
'<(INTERMEDIATE_DIR)/snapshot.cc',
],
'actions': [
@@ -182,6 +183,7 @@
'sources': [
'<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
'<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc',
'../../src/snapshot-empty.cc',
],
'conditions': [
@@ -200,9 +202,38 @@
}],
]
},
+ { 'target_name': 'generate_trig_table',
+ 'type': 'none',
+ 'conditions': [
+ ['want_separate_host_toolset==1', {
+ 'toolsets': ['host', 'target'],
+ }, {
+ 'toolsets': ['target'],
+ }],
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate',
+ 'inputs': [
+ '../../tools/generate-trig-table.py',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/trig-table.cc',
+ ],
+ 'action': [
+ 'python',
+ '../../tools/generate-trig-table.py',
+ '<@(_outputs)',
+ ],
+ },
+ ]
+ },
{
'target_name': 'v8_base.<(v8_target_arch)',
'type': 'static_library',
+ 'dependencies': [
+ 'generate_trig_table',
+ ],
'variables': {
'optimize': 'max',
},
@@ -280,6 +311,8 @@
'../../src/debug-agent.h',
'../../src/debug.cc',
'../../src/debug.h',
+ '../../src/default-platform.cc',
+ '../../src/default-platform.h',
'../../src/deoptimizer.cc',
'../../src/deoptimizer.h',
'../../src/disasm.h',
@@ -886,6 +919,12 @@
'<(icu_gyp_path):icudata',
],
}],
+ ['v8_use_default_platform==0', {
+ 'sources!': [
+ '../../src/default-platform.cc',
+ '../../src/default-platform.h',
+ ],
+ }],
],
},
{
diff --git a/tools/push-to-trunk/auto_roll.py b/tools/push-to-trunk/auto_roll.py
index 9547301..cb990cd 100755
--- a/tools/push-to-trunk/auto_roll.py
+++ b/tools/push-to-trunk/auto_roll.py
@@ -29,7 +29,6 @@
import optparse
import re
import sys
-import urllib2
from common_includes import *
@@ -40,8 +39,7 @@
class Preparation(Step):
- def __init__(self):
- Step.__init__(self, "Preparation.")
+ MESSAGE = "Preparation."
def RunStep(self):
self.InitialEnvironmentChecks()
@@ -49,8 +47,7 @@
class FetchLatestRevision(Step):
- def __init__(self):
- Step.__init__(self, "Fetching latest V8 revision.")
+ MESSAGE = "Fetching latest V8 revision."
def RunStep(self):
log = self.Git("svn log -1 --oneline").strip()
@@ -61,25 +58,15 @@
class FetchLKGR(Step):
- def __init__(self):
- Step.__init__(self, "Fetching V8 LKGR.")
+ MESSAGE = "Fetching V8 LKGR."
def RunStep(self):
lkgr_url = "https://v8-status.appspot.com/lkgr"
- try:
- # pylint: disable=E1121
- url_fh = urllib2.urlopen(lkgr_url, None, 60)
- except urllib2.URLError:
- self.Die("URLException while fetching %s" % lkgr_url)
- try:
- self.Persist("lkgr", url_fh.read())
- finally:
- url_fh.close()
+ self.Persist("lkgr", self.ReadURL(lkgr_url))
class PushToTrunk(Step):
- def __init__(self):
- Step.__init__(self, "Pushing to trunk if possible.")
+ MESSAGE = "Pushing to trunk if possible."
def RunStep(self):
self.RestoreIfUnset("latest")
@@ -94,6 +81,18 @@
% (latest, lkgr))
+def RunAutoRoll(config,
+ options,
+ side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
+ step_classes = [
+ Preparation,
+ FetchLatestRevision,
+ FetchLKGR,
+ PushToTrunk,
+ ]
+ RunScript(step_classes, config, options, side_effect_handler)
+
+
def BuildOptions():
result = optparse.OptionParser()
result.add_option("-s", "--step", dest="s",
@@ -105,15 +104,7 @@
def Main():
parser = BuildOptions()
(options, args) = parser.parse_args()
-
- step_classes = [
- Preparation,
- FetchLatestRevision,
- FetchLKGR,
- PushToTrunk,
- ]
-
- RunScript(step_classes, CONFIG, options, DEFAULT_SIDE_EFFECT_HANDLER)
+ RunAutoRoll(CONFIG, options)
if __name__ == "__main__":
sys.exit(Main())
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index b6f9761..eaa3d20 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -31,6 +31,7 @@
import subprocess
import sys
import textwrap
+import urllib2
PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME"
TEMP_BRANCH = "TEMP_BRANCH"
@@ -69,6 +70,10 @@
def Fill80(line):
+ # Replace tabs and remove surrounding space.
+ line = re.sub(r"\t", r" ", line.strip())
+
+ # Format with 8 characters indentation and line width 80.
return textwrap.fill(line, width=80, initial_indent=" ",
subsequent_indent=" ")
@@ -96,7 +101,7 @@
for (title, body, author) in commit_messages:
# TODO(machenbach): Reload the commit description from rietveld in order to
# catch late changes.
- title = title.rstrip()
+ title = title.strip()
if auto_format:
# Only add commits that set the LOG flag correctly.
log_exp = r"^[ \t]*LOG[ \t]*=[ \t]*(?:Y(?:ES)?)|TRUE"
@@ -114,7 +119,7 @@
# indentation afterwards.
# Add the commit's title line.
- result += "%s\n" % title
+ result += "%s\n" % Fill80(title)
added_titles.add(title)
# Add bug references.
@@ -122,7 +127,7 @@
# Append the commit's author for reference if not in auto-format mode.
if not auto_format:
- result += "%s\n" % author.rstrip()
+ result += "%s\n" % Fill80("(%s)" % author.strip())
result += "\n"
return result
@@ -192,40 +197,35 @@
def ReadLine(self):
return sys.stdin.readline().strip()
+ def ReadURL(self, url):
+ # pylint: disable=E1121
+ url_fh = urllib2.urlopen(url, None, 60)
+ try:
+ return url_fh.read()
+ finally:
+ url_fh.close()
+
DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler()
class Step(object):
- def __init__(self, text="", requires=None):
+ def __init__(self, text, requires, number, config, state, options, handler):
self._text = text
- self._number = -1
- self._options = None
self._requires = requires
- self._side_effect_handler = DEFAULT_SIDE_EFFECT_HANDLER
-
- def SetNumber(self, number):
self._number = number
-
- def SetConfig(self, config):
self._config = config
-
- def SetState(self, state):
self._state = state
-
- def SetOptions(self, options):
self._options = options
-
- def SetSideEffectHandler(self, handler):
self._side_effect_handler = handler
+ assert self._number >= 0
+ assert self._config is not None
+ assert self._state is not None
+ assert self._side_effect_handler is not None
def Config(self, key):
return self._config[key]
def Run(self):
- assert self._number >= 0
- assert self._config is not None
- assert self._state is not None
- assert self._side_effect_handler is not None
if self._requires:
self.RestoreIfUnset(self._requires)
if not self._state[self._requires]:
@@ -251,6 +251,9 @@
return self._side_effect_handler.Command(os.environ["EDITOR"], args,
pipe=False)
+ def ReadURL(self, url):
+ return self._side_effect_handler.ReadURL(url)
+
def Die(self, msg=""):
if msg != "":
print "Error: %s" % msg
@@ -399,8 +402,7 @@
class UploadStep(Step):
- def __init__(self):
- Step.__init__(self, "Upload for code review.")
+ MESSAGE = "Upload for code review."
def RunStep(self):
if self._options.r:
@@ -418,24 +420,35 @@
self.Die("'git cl upload' failed, please try again.")
+def MakeStep(step_class=Step, number=0, state=None, config=None,
+ options=None, side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
+ # Allow to pass in empty dictionaries.
+ state = state if state is not None else {}
+ config = config if config is not None else {}
+
+ try:
+ message = step_class.MESSAGE
+ except AttributeError:
+ message = step_class.__name__
+ try:
+ requires = step_class.REQUIRES
+ except AttributeError:
+ requires = None
+
+ return step_class(message, requires, number=number, config=config,
+ state=state, options=options,
+ handler=side_effect_handler)
+
+
def RunScript(step_classes,
config,
options,
side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
state = {}
steps = []
- number = 0
-
- for step_class in step_classes:
- # TODO(machenbach): Factory methods.
- step = step_class()
- step.SetNumber(number)
- step.SetConfig(config)
- step.SetOptions(options)
- step.SetState(state)
- step.SetSideEffectHandler(side_effect_handler)
- steps.append(step)
- number += 1
+ for (number, step_class) in enumerate(step_classes):
+ steps.append(MakeStep(step_class, number, state, config,
+ options, side_effect_handler))
for step in steps[options.s:]:
step.Run()
diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py
index 7278323..24dfb67 100755
--- a/tools/push-to-trunk/push_to_trunk.py
+++ b/tools/push-to-trunk/push_to_trunk.py
@@ -53,8 +53,7 @@
class Preparation(Step):
- def __init__(self):
- Step.__init__(self, "Preparation.")
+ MESSAGE = "Preparation."
def RunStep(self):
self.InitialEnvironmentChecks()
@@ -64,8 +63,7 @@
class FreshBranch(Step):
- def __init__(self):
- Step.__init__(self, "Create a fresh branch.")
+ MESSAGE = "Create a fresh branch."
def RunStep(self):
args = "checkout -b %s svn/bleeding_edge" % self.Config(BRANCHNAME)
@@ -74,8 +72,7 @@
class DetectLastPush(Step):
- def __init__(self):
- Step.__init__(self, "Detect commit ID of last push to trunk.")
+ MESSAGE = "Detect commit ID of last push to trunk."
def RunStep(self):
last_push = (self._options.l or
@@ -92,8 +89,7 @@
class PrepareChangeLog(Step):
- def __init__(self):
- Step.__init__(self, "Prepare raw ChangeLog entry.")
+ MESSAGE = "Prepare raw ChangeLog entry."
def RunStep(self):
self.RestoreIfUnset("last_push")
@@ -115,9 +111,9 @@
# Cache raw commit messages.
commit_messages = [
[
- self.Git("log -1 %s --format=\"%%w(80,8,8)%%s\"" % commit),
+ self.Git("log -1 %s --format=\"%%s\"" % commit),
self.Git("log -1 %s --format=\"%%B\"" % commit),
- self.Git("log -1 %s --format=\"%%w(80,8,8)(%%an)\"" % commit),
+ self.Git("log -1 %s --format=\"%%an\"" % commit),
] for commit in commits.splitlines()
]
@@ -137,8 +133,7 @@
class EditChangeLog(Step):
- def __init__(self):
- Step.__init__(self, "Edit ChangeLog entry.")
+ MESSAGE = "Edit ChangeLog entry."
def RunStep(self):
print ("Please press <Return> to have your EDITOR open the ChangeLog "
@@ -152,14 +147,10 @@
handle, new_changelog = tempfile.mkstemp()
os.close(handle)
- # (1) Strip comments, (2) eliminate tabs, (3) fix too little and (4) too
- # much indentation, and (5) eliminate trailing whitespace.
+ # Strip comments and reformat with correct indentation.
changelog_entry = FileToText(self.Config(CHANGELOG_ENTRY_FILE)).rstrip()
changelog_entry = StripComments(changelog_entry)
- changelog_entry = MSub(r"\t", r" ", changelog_entry)
- changelog_entry = MSub(r"^ {1,7}([^ ])", r" \1", changelog_entry)
- changelog_entry = MSub(r"^ {9,80}([^ ])", r" \1", changelog_entry)
- changelog_entry = MSub(r" +$", r"", changelog_entry)
+ changelog_entry = "\n".join(map(Fill80, changelog_entry.splitlines()))
if changelog_entry == "":
self.Die("Empty ChangeLog entry.")
@@ -174,8 +165,7 @@
class IncrementVersion(Step):
- def __init__(self):
- Step.__init__(self, "Increment version number.")
+ MESSAGE = "Increment version number."
def RunStep(self):
self.RestoreIfUnset("build")
@@ -197,8 +187,7 @@
class CommitLocal(Step):
- def __init__(self):
- Step.__init__(self, "Commit to local branch.")
+ MESSAGE = "Commit to local branch."
def RunStep(self):
self.RestoreVersionIfUnset("new_")
@@ -212,8 +201,7 @@
class CommitRepository(Step):
- def __init__(self):
- Step.__init__(self, "Commit to the repository.")
+ MESSAGE = "Commit to the repository."
def RunStep(self):
self.WaitForLGTM()
@@ -227,9 +215,8 @@
class StragglerCommits(Step):
- def __init__(self):
- Step.__init__(self, "Fetch straggler commits that sneaked in since this "
- "script was started.")
+ MESSAGE = ("Fetch straggler commits that sneaked in since this script was "
+ "started.")
def RunStep(self):
if self.Git("svn fetch") is None:
@@ -242,8 +229,7 @@
class SquashCommits(Step):
- def __init__(self):
- Step.__init__(self, "Squash commits into one.")
+ MESSAGE = "Squash commits into one."
def RunStep(self):
# Instead of relying on "git rebase -i", we'll just create a diff, because
@@ -285,8 +271,7 @@
class NewBranch(Step):
- def __init__(self):
- Step.__init__(self, "Create a new branch from trunk.")
+ MESSAGE = "Create a new branch from trunk."
def RunStep(self):
if self.Git("checkout -b %s svn/trunk" % self.Config(TRUNKBRANCH)) is None:
@@ -295,8 +280,7 @@
class ApplyChanges(Step):
- def __init__(self):
- Step.__init__(self, "Apply squashed changes.")
+ MESSAGE = "Apply squashed changes."
def RunStep(self):
self.ApplyPatch(self.Config(PATCH_FILE))
@@ -304,8 +288,7 @@
class SetVersion(Step):
- def __init__(self):
- Step.__init__(self, "Set correct version for trunk.")
+ MESSAGE = "Set correct version for trunk."
def RunStep(self):
self.RestoreVersionIfUnset()
@@ -326,8 +309,7 @@
class CommitTrunk(Step):
- def __init__(self):
- Step.__init__(self, "Commit to local trunk branch.")
+ MESSAGE = "Commit to local trunk branch."
def RunStep(self):
self.Git("add \"%s\"" % self.Config(VERSION_FILE))
@@ -337,8 +319,7 @@
class SanityCheck(Step):
- def __init__(self):
- Step.__init__(self, "Sanity check.")
+ MESSAGE = "Sanity check."
def RunStep(self):
if not self.Confirm("Please check if your local checkout is sane: Inspect "
@@ -348,8 +329,7 @@
class CommitSVN(Step):
- def __init__(self):
- Step.__init__(self, "Commit to SVN.")
+ MESSAGE = "Commit to SVN."
def RunStep(self):
result = self.Git("svn dcommit 2>&1")
@@ -374,8 +354,7 @@
class TagRevision(Step):
- def __init__(self):
- Step.__init__(self, "Tag the new revision.")
+ MESSAGE = "Tag the new revision."
def RunStep(self):
self.RestoreVersionIfUnset()
@@ -387,8 +366,7 @@
class CheckChromium(Step):
- def __init__(self):
- Step.__init__(self, "Ask for chromium checkout.")
+ MESSAGE = "Ask for chromium checkout."
def Run(self):
chrome_path = self._options.c
@@ -404,8 +382,8 @@
class SwitchChromium(Step):
- def __init__(self):
- Step.__init__(self, "Switch to Chromium checkout.", requires="chrome_path")
+ MESSAGE = "Switch to Chromium checkout."
+ REQUIRES = "chrome_path"
def RunStep(self):
v8_path = os.getcwd()
@@ -421,9 +399,8 @@
class UpdateChromiumCheckout(Step):
- def __init__(self):
- Step.__init__(self, "Update the checkout and create a new branch.",
- requires="chrome_path")
+ MESSAGE = "Update the checkout and create a new branch."
+ REQUIRES = "chrome_path"
def RunStep(self):
os.chdir(self._state["chrome_path"])
@@ -439,8 +416,8 @@
class UploadCL(Step):
- def __init__(self):
- Step.__init__(self, "Create and upload CL.", requires="chrome_path")
+ MESSAGE = "Create and upload CL."
+ REQUIRES = "chrome_path"
def RunStep(self):
os.chdir(self._state["chrome_path"])
@@ -474,8 +451,8 @@
class SwitchV8(Step):
- def __init__(self):
- Step.__init__(self, "Returning to V8 checkout.", requires="chrome_path")
+ MESSAGE = "Returning to V8 checkout."
+ REQUIRES = "chrome_path"
def RunStep(self):
self.RestoreIfUnset("v8_path")
@@ -483,8 +460,7 @@
class CleanUp(Step):
- def __init__(self):
- Step.__init__(self, "Done!")
+ MESSAGE = "Done!"
def RunStep(self):
self.RestoreVersionIfUnset()
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index 42b26cf..5e2340e 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -34,6 +34,7 @@
from common_includes import *
import push_to_trunk
from push_to_trunk import *
+import auto_roll
TEST_CONFIG = {
@@ -67,18 +68,18 @@
def testMakeChangeLogBodySimple(self):
commits = [
- [" Title text 1",
+ ["Title text 1",
"Title text 1\n\nBUG=\n",
- " author1@chromium.org"],
- [" Title text 2",
+ "author1@chromium.org"],
+ ["Title text 2",
"Title text 2\n\nBUG=1234\n",
- " author2@chromium.org"],
+ "author2@chromium.org"],
]
self.assertEquals(" Title text 1\n"
- " author1@chromium.org\n\n"
+ " (author1@chromium.org)\n\n"
" Title text 2\n"
" (Chromium issue 1234)\n"
- " author2@chromium.org\n\n",
+ " (author2@chromium.org)\n\n",
MakeChangeLogBody(commits))
def testMakeChangeLogBodyEmpty(self):
@@ -86,18 +87,18 @@
def testMakeChangeLogBodyAutoFormat(self):
commits = [
- [" Title text 1",
+ ["Title text 1",
"Title text 1\nLOG=y\nBUG=\n",
- " author1@chromium.org"],
- [" Title text 2",
+ "author1@chromium.org"],
+ ["Title text 2",
"Title text 2\n\nBUG=1234\n",
- " author2@chromium.org"],
- [" Title text 3",
+ "author2@chromium.org"],
+ ["Title text 3",
"Title text 3\n\nBUG=1234\nLOG = Yes\n",
- " author3@chromium.org"],
- [" Title text 3",
+ "author3@chromium.org"],
+ ["Title text 3",
"Title text 4\n\nBUG=1234\nLOG=\n",
- " author4@chromium.org"],
+ "author4@chromium.org"],
]
self.assertEquals(" Title text 1\n\n"
" Title text 3\n"
@@ -178,6 +179,51 @@
"BUG=1234567890123456789\n"
"BUG=1234567890\n"))
+
+class SimpleMock(object):
+ def __init__(self, name):
+ self._name = name
+ self._recipe = []
+ self._index = -1
+
+ def Expect(self, recipe):
+ self._recipe = recipe
+
+ def Call(self, *args):
+ self._index += 1
+ try:
+ expected_call = self._recipe[self._index]
+ except IndexError:
+ raise Exception("Calling %s %s" % (name, " ".join(args)))
+
+ # Pack expectations without arguments into a list.
+ if not isinstance(expected_call, list):
+ expected_call = [expected_call]
+
+ # The number of arguments in the expectation must match the actual
+ # arguments.
+ if len(args) > len(expected_call):
+ raise Exception("When calling %s with arguments, the expectations "
+ "must consist of at least as many arguments.")
+
+ # Compare expected and actual arguments.
+ for (expected_arg, actual_arg) in zip(expected_call, args):
+ if expected_arg != actual_arg:
+ raise Exception("Expected: %s - Actual: %s"
+ % (expected_arg, actual_arg))
+
+ # The expectation list contains a mandatory return value and an optional
+ # callback for checking the context at the time of the call.
+ if len(expected_call) == len(args) + 2:
+ expected_call[len(args) + 1]()
+ return expected_call[len(args)]
+
+ def AssertFinished(self):
+ if self._index < len(self._recipe) -1:
+ raise Exception("Called %s too seldom: %d vs. %d"
+ % (self._name, self._index, len(self._recipe)))
+
+
class ScriptTest(unittest.TestCase):
def MakeEmptyTempFile(self):
handle, name = tempfile.mkstemp()
@@ -199,26 +245,12 @@
return name
def MakeStep(self, step_class=Step, state=None):
- state = state or {}
- step = step_class()
- step.SetConfig(TEST_CONFIG)
- step.SetState(state)
- step.SetNumber(0)
- step.SetSideEffectHandler(self)
- return step
+ """Convenience wrapper."""
+ return MakeStep(step_class=step_class, number=0, state=state,
+ config=TEST_CONFIG, options=None, side_effect_handler=self)
def GitMock(self, cmd, args="", pipe=True):
- self._git_index += 1
- try:
- git_invocation = self._git_recipe[self._git_index]
- except IndexError:
- raise Exception("Calling git %s" % args)
- if git_invocation[0] != args:
- raise Exception("Expected: %s - Actual: %s" % (git_invocation[0], args))
- if len(git_invocation) == 3:
- # Run optional function checking the context during this git command.
- git_invocation[2]()
- return git_invocation[1]
+ return self._git_mock.Call(args)
def LogMock(self, cmd, args=""):
print "Log: %s %s" % (cmd, args)
@@ -232,17 +264,27 @@
return ScriptTest.MOCKS[cmd](self, cmd, args)
def ReadLine(self):
- self._rl_index += 1
- try:
- return self._rl_recipe[self._rl_index]
- except IndexError:
- raise Exception("Calling readline too often")
+ return self._rl_mock.Call()
+
+ def ReadURL(self, url):
+ return self._url_mock.Call(url)
+
+ def ExpectGit(self, *args):
+ """Convenience wrapper."""
+ self._git_mock.Expect(*args)
+
+ def ExpectReadline(self, *args):
+ """Convenience wrapper."""
+ self._rl_mock.Expect(*args)
+
+ def ExpectReadURL(self, *args):
+ """Convenience wrapper."""
+ self._url_mock.Expect(*args)
def setUp(self):
- self._git_recipe = []
- self._git_index = -1
- self._rl_recipe = []
- self._rl_index = -1
+ self._git_mock = SimpleMock("git")
+ self._rl_mock = SimpleMock("readline")
+ self._url_mock = SimpleMock("readurl")
self._tmp_files = []
def tearDown(self):
@@ -253,12 +295,9 @@
if os.path.exists(name):
os.remove(name)
- if self._git_index < len(self._git_recipe) -1:
- raise Exception("Called git too seldom: %d vs. %d" %
- (self._git_index, len(self._git_recipe)))
- if self._rl_index < len(self._rl_recipe) -1:
- raise Exception("Too little input: %d vs. %d" %
- (self._rl_index, len(self._rl_recipe)))
+ self._git_mock.AssertFinished()
+ self._rl_mock.AssertFinished()
+ self._url_mock.AssertFinished()
def testPersistRestore(self):
self.MakeStep().Persist("test1", "")
@@ -270,12 +309,12 @@
self.assertTrue(Command("git", "--version").startswith("git version"))
def testGitMock(self):
- self._git_recipe = [["--version", "git version 1.2.3"], ["dummy", ""]]
+ self.ExpectGit([["--version", "git version 1.2.3"], ["dummy", ""]])
self.assertEquals("git version 1.2.3", self.MakeStep().Git("--version"))
self.assertEquals("", self.MakeStep().Git("dummy"))
def testCommonPrepareDefault(self):
- self._git_recipe = [
+ self.ExpectGit([
["status -s -uno", ""],
["status -s -b -uno", "## some_branch"],
["svn fetch", ""],
@@ -283,33 +322,33 @@
["branch -D %s" % TEST_CONFIG[TEMP_BRANCH], ""],
["checkout -b %s" % TEST_CONFIG[TEMP_BRANCH], ""],
["branch", ""],
- ]
- self._rl_recipe = ["Y"]
+ ])
+ self.ExpectReadline(["Y"])
self.MakeStep().CommonPrepare()
self.MakeStep().PrepareBranch()
self.assertEquals("some_branch", self.MakeStep().Restore("current_branch"))
def testCommonPrepareNoConfirm(self):
- self._git_recipe = [
+ self.ExpectGit([
["status -s -uno", ""],
["status -s -b -uno", "## some_branch"],
["svn fetch", ""],
["branch", " branch1\n* %s" % TEST_CONFIG[TEMP_BRANCH]],
- ]
- self._rl_recipe = ["n"]
+ ])
+ self.ExpectReadline(["n"])
self.MakeStep().CommonPrepare()
self.assertRaises(Exception, self.MakeStep().PrepareBranch)
self.assertEquals("some_branch", self.MakeStep().Restore("current_branch"))
def testCommonPrepareDeleteBranchFailure(self):
- self._git_recipe = [
+ self.ExpectGit([
["status -s -uno", ""],
["status -s -b -uno", "## some_branch"],
["svn fetch", ""],
["branch", " branch1\n* %s" % TEST_CONFIG[TEMP_BRANCH]],
["branch -D %s" % TEST_CONFIG[TEMP_BRANCH], None],
- ]
- self._rl_recipe = ["Y"]
+ ])
+ self.ExpectReadline(["Y"])
self.MakeStep().CommonPrepare()
self.assertRaises(Exception, self.MakeStep().PrepareBranch)
self.assertEquals("some_branch", self.MakeStep().Restore("current_branch"))
@@ -357,21 +396,18 @@
TEST_CONFIG[VERSION_FILE] = self.MakeTempVersionFile()
TEST_CONFIG[CHANGELOG_ENTRY_FILE] = self.MakeEmptyTempFile()
- self._git_recipe = [
+ self.ExpectGit([
["log 1234..HEAD --format=%H", "rev1\nrev2\nrev3"],
- ["log -1 rev1 --format=\"%w(80,8,8)%s\"", " Title text 1"],
+ ["log -1 rev1 --format=\"%s\"", "Title text 1"],
["log -1 rev1 --format=\"%B\"", "Title\n\nBUG=\nLOG=y\n"],
- ["log -1 rev1 --format=\"%w(80,8,8)(%an)\"",
- " author1@chromium.org"],
- ["log -1 rev2 --format=\"%w(80,8,8)%s\"", " Title text 2"],
+ ["log -1 rev1 --format=\"%an\"", "author1@chromium.org"],
+ ["log -1 rev2 --format=\"%s\"", "Title text 2"],
["log -1 rev2 --format=\"%B\"", "Title\n\nBUG=123\nLOG= \n"],
- ["log -1 rev2 --format=\"%w(80,8,8)(%an)\"",
- " author2@chromium.org"],
- ["log -1 rev3 --format=\"%w(80,8,8)%s\"", " Title text 3"],
+ ["log -1 rev2 --format=\"%an\"", "author2@chromium.org"],
+ ["log -1 rev3 --format=\"%s\"", "Title text 3"],
["log -1 rev3 --format=\"%B\"", "Title\n\nBUG=321\nLOG=true\n"],
- ["log -1 rev3 --format=\"%w(80,8,8)(%an)\"",
- " author3@chromium.org"],
- ]
+ ["log -1 rev3 --format=\"%an\"", "author3@chromium.org"],
+ ])
self.MakeStep().Persist("last_push", "1234")
self.MakeStep(PrepareChangeLog).Run()
@@ -394,15 +430,15 @@
# All lines starting with # will be stripped\\.
#
# Title text 1
-# author1@chromium\\.org
+# \\(author1@chromium\\.org\\)
#
# Title text 2
# \\(Chromium issue 123\\)
-# author2@chromium\\.org
+# \\(author2@chromium\\.org\\)
#
# Title text 3
# \\(Chromium issue 321\\)
-# author3@chromium\\.org
+# \\(author3@chromium\\.org\\)
#
#"""
@@ -419,9 +455,9 @@
TextToFile(" New \n\tLines \n", TEST_CONFIG[CHANGELOG_ENTRY_FILE])
os.environ["EDITOR"] = "vi"
- self._rl_recipe = [
+ self.ExpectReadline([
"", # Open editor.
- ]
+ ])
self.MakeStep(EditChangeLog).Run()
@@ -432,9 +468,9 @@
TEST_CONFIG[VERSION_FILE] = self.MakeTempVersionFile()
self.MakeStep().Persist("build", "5")
- self._rl_recipe = [
+ self.ExpectReadline([
"Y", # Increment build number.
- ]
+ ])
self.MakeStep(IncrementVersion).Run()
@@ -470,9 +506,9 @@
f.write(" Performance and stability improvements on all "
"platforms.\n")
- self._git_recipe = [
+ self.ExpectGit([
["diff svn/trunk hash1", "patch content"],
- ]
+ ])
self.MakeStep().Persist("prepare_commit_hash", "hash1")
self.MakeStep().Persist("date", "1999-11-11")
@@ -505,7 +541,7 @@
self.assertTrue(re.search(r"Version 3.22.5", cl))
self.assertTrue(re.search(r" Log text 1", cl))
self.assertTrue(re.search(r" \(issue 321\)", cl))
- self.assertFalse(re.search(r" author1@chromium\.org", cl))
+ self.assertFalse(re.search(r" \(author1@chromium\.org\)", cl))
# Make sure all comments got stripped.
self.assertFalse(re.search(r"^#", cl, flags=re.M))
@@ -528,7 +564,7 @@
self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version))
force_flag = " -f" if force else ""
- self._git_recipe = [
+ self.ExpectGit([
["status -s -uno", ""],
["status -s -b -uno", "## some_branch\n"],
["svn fetch", ""],
@@ -540,10 +576,9 @@
["log -1 --format=%H ChangeLog", "1234\n"],
["log -1 1234", "Last push ouput\n"],
["log 1234..HEAD --format=%H", "rev1\n"],
- ["log -1 rev1 --format=\"%w(80,8,8)%s\"", " Log text 1.\n"],
+ ["log -1 rev1 --format=\"%s\"", "Log text 1.\n"],
["log -1 rev1 --format=\"%B\"", "Text\nLOG=YES\nBUG=v8:321\nText\n"],
- ["log -1 rev1 --format=\"%w(80,8,8)(%an)\"",
- " author1@chromium.org\n"],
+ ["log -1 rev1 --format=\"%an\"", "author1@chromium.org\n"],
[("commit -a -m \"Prepare push to trunk. "
"Now working on version 3.22.6.\""),
" 2 files changed\n",
@@ -575,8 +610,8 @@
["branch -D %s" % TEST_CONFIG[TEMP_BRANCH], ""],
["branch -D %s" % TEST_CONFIG[BRANCHNAME], ""],
["branch -D %s" % TEST_CONFIG[TRUNKBRANCH], ""],
- ]
- self._rl_recipe = [
+ ])
+ self.ExpectReadline([
"Y", # Confirm last push.
"", # Open editor.
"Y", # Increment build number.
@@ -585,13 +620,13 @@
"LGTM", # Enter LGTM for V8 CL.
"Y", # Sanity check.
"reviewer@chromium.org", # Chromium reviewer.
- ]
+ ])
if force:
# TODO(machenbach): The lgtm for the prepare push is just temporary.
# There should be no user input in "force" mode.
- self._rl_recipe = [
+ self.ExpectReadline([
"LGTM", # Enter LGTM for V8 CL.
- ]
+ ])
class Options( object ):
pass
@@ -622,3 +657,32 @@
def testPushToTrunkForced(self):
self._PushToTrunk(force=True)
+
+ def testAutoRoll(self):
+ TEST_CONFIG[DOT_GIT_LOCATION] = self.MakeEmptyTempFile()
+
+ # TODO(machenbach): Get rid of the editor check in automatic mode.
+ os.environ["EDITOR"] = "vi"
+
+ self.ExpectReadURL([
+ ["https://v8-status.appspot.com/lkgr", "100"],
+ ])
+
+ self.ExpectGit([
+ ["status -s -uno", ""],
+ ["status -s -b -uno", "## some_branch\n"],
+ ["svn fetch", ""],
+ ["svn log -1 --oneline", "r101 | Text"],
+ ])
+
+ # TODO(machenbach): Make a convenience wrapper for this.
+ class Options( object ):
+ pass
+
+ options = Options()
+ options.s = 0
+
+ auto_roll.RunAutoRoll(TEST_CONFIG, options, self)
+
+ self.assertEquals("100", self.MakeStep().Restore("lkgr"))
+ self.assertEquals("101", self.MakeStep().Restore("latest"))