Version 3.24.6
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@18396 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 9a68f63..1f5b165 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2487,13 +2487,7 @@
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsSmi()) return true;
if (obj->IsNumber()) {
- double value = obj->Number();
- static const i::DoubleRepresentation minus_zero(-0.0);
- i::DoubleRepresentation rep(value);
- if (rep.bits == minus_zero.bits) {
- return false;
- }
- return i::FastI2D(i::FastD2I(value)) == value;
+ return i::IsInt32Double(obj->Number());
}
return false;
}
@@ -2504,12 +2498,10 @@
if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
if (obj->IsNumber()) {
double value = obj->Number();
- static const i::DoubleRepresentation minus_zero(-0.0);
- i::DoubleRepresentation rep(value);
- if (rep.bits == minus_zero.bits) {
- return false;
- }
- return i::FastUI2D(i::FastD2UI(value)) == value;
+ return !i::IsMinusZero(value) &&
+ value >= 0 &&
+ value <= i::kMaxUInt32 &&
+ value == i::FastUI2D(i::FastD2UI(value));
}
return false;
}
@@ -6500,6 +6492,17 @@
}
+void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
+ reinterpret_cast<i::Isolate*>(this)->stack_guard()->RequestInterrupt(
+ callback, data);
+}
+
+
+void Isolate::ClearInterrupt() {
+ reinterpret_cast<i::Isolate*>(this)->stack_guard()->ClearInterrupt();
+}
+
+
Isolate* Isolate::GetCurrent() {
i::Isolate* isolate = i::Isolate::UncheckedCurrent();
return reinterpret_cast<Isolate*>(isolate);
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 4b65845..d95b746 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -803,7 +803,7 @@
// r1 - isolate
FrameScope scope(masm, StackFrame::MANUAL);
__ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
- __ PrepareCallCFunction(1, 0, r2);
+ __ PrepareCallCFunction(2, 0, r2);
__ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
__ CallCFunction(
ExternalReference::get_make_code_young_function(masm->isolate()), 2);
@@ -836,7 +836,7 @@
// r1 - isolate
FrameScope scope(masm, StackFrame::MANUAL);
__ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
- __ PrepareCallCFunction(1, 0, r2);
+ __ PrepareCallCFunction(2, 0, r2);
__ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
__ CallCFunction(ExternalReference::get_mark_code_as_executed_function(
masm->isolate()), 2);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 5f6076b..1e36b35 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -815,11 +815,11 @@
const Register scratch) {
static const DoubleRepresentation minus_zero(-0.0);
static const DoubleRepresentation zero(0.0);
- DoubleRepresentation value(imm);
+ DoubleRepresentation value_rep(imm);
// Handle special values first.
- if (value.bits == zero.bits) {
+ if (value_rep == zero) {
vmov(dst, kDoubleRegZero);
- } else if (value.bits == minus_zero.bits) {
+ } else if (value_rep == minus_zero) {
vneg(dst, kDoubleRegZero);
} else {
vmov(dst, imm, scratch);
diff --git a/src/ast.h b/src/ast.h
index cf3ef92..f8de9be 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -39,7 +39,6 @@
#include "small-pointer-list.h"
#include "smart-pointers.h"
#include "token.h"
-#include "type-info.h" // TODO(rossberg): this should eventually be removed
#include "types.h"
#include "utils.h"
#include "variables.h"
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 0a9fdcb..c47bdf5 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -545,7 +545,7 @@
map->AppendDescriptor(&d, witness);
}
{ // Add name.
- CallbacksDescriptor d(*factory()->name_string(), *name, rw_attribs);
+ CallbacksDescriptor d(*factory()->name_string(), *name, ro_attribs);
map->AppendDescriptor(&d, witness);
}
{ // Add arguments.
diff --git a/src/codegen.h b/src/codegen.h
index b271d21..d160f13 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -30,7 +30,6 @@
#include "code-stubs.h"
#include "runtime.h"
-#include "type-info.h"
// Include the declaration of the architecture defined class CodeGenerator.
// The contract to the shared code is that the the CodeGenerator is a subclass
diff --git a/src/conversions.h b/src/conversions.h
index 7aa2d3f..f850f58 100644
--- a/src/conversions.h
+++ b/src/conversions.h
@@ -72,7 +72,7 @@
// The result is unspecified if x is infinite or NaN, or if the rounded
// integer value is outside the range of type int.
inline int FastD2I(double x) {
- return static_cast<int>(x);
+ return static_cast<int32_t>(x);
}
inline unsigned int FastD2UI(double x);
diff --git a/src/execution.cc b/src/execution.cc
index c0e9a64..a9f72b3 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -540,6 +540,48 @@
}
+void StackGuard::RequestInterrupt(InterruptCallback callback, void* data) {
+ ExecutionAccess access(isolate_);
+ thread_local_.interrupt_flags_ |= API_INTERRUPT;
+ thread_local_.interrupt_callback_ = callback;
+ thread_local_.interrupt_callback_data_ = data;
+ set_interrupt_limits(access);
+}
+
+
+void StackGuard::ClearInterrupt() {
+ thread_local_.interrupt_callback_ = 0;
+ thread_local_.interrupt_callback_data_ = 0;
+ Continue(API_INTERRUPT);
+}
+
+
+bool StackGuard::IsAPIInterrupt() {
+ ExecutionAccess access(isolate_);
+ return thread_local_.interrupt_flags_ & API_INTERRUPT;
+}
+
+
+void StackGuard::InvokeInterruptCallback() {
+ InterruptCallback callback = 0;
+ void* data = 0;
+
+ {
+ ExecutionAccess access(isolate_);
+ callback = thread_local_.interrupt_callback_;
+ data = thread_local_.interrupt_callback_data_;
+ thread_local_.interrupt_callback_ = NULL;
+ thread_local_.interrupt_callback_data_ = NULL;
+ }
+
+ if (callback != NULL) {
+ VMState<EXTERNAL> state(isolate_);
+ HandleScope handle_scope(isolate_);
+ callback(reinterpret_cast<v8::Isolate*>(isolate_), data);
+ }
+}
+
+
char* StackGuard::ArchiveStackGuard(char* to) {
ExecutionAccess access(isolate_);
OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
@@ -581,6 +623,8 @@
nesting_ = 0;
postpone_interrupts_nesting_ = 0;
interrupt_flags_ = 0;
+ interrupt_callback_ = NULL;
+ interrupt_callback_data_ = NULL;
}
@@ -601,6 +645,8 @@
nesting_ = 0;
postpone_interrupts_nesting_ = 0;
interrupt_flags_ = 0;
+ interrupt_callback_ = NULL;
+ interrupt_callback_data_ = NULL;
return should_set_stack_limits;
}
@@ -936,6 +982,11 @@
return isolate->heap()->undefined_value();
}
+ if (stack_guard->IsAPIInterrupt()) {
+ stack_guard->InvokeInterruptCallback();
+ stack_guard->Continue(API_INTERRUPT);
+ }
+
if (stack_guard->IsGCRequest()) {
isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
"StackGuard GC request");
diff --git a/src/execution.h b/src/execution.h
index eda416c..3e62d87 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -43,7 +43,8 @@
TERMINATE = 1 << 4,
GC_REQUEST = 1 << 5,
FULL_DEOPT = 1 << 6,
- INSTALL_CODE = 1 << 7
+ INSTALL_CODE = 1 << 7,
+ API_INTERRUPT = 1 << 8
};
@@ -222,6 +223,11 @@
void FullDeopt();
void Continue(InterruptFlag after_what);
+ void RequestInterrupt(InterruptCallback callback, void* data);
+ void ClearInterrupt();
+ bool IsAPIInterrupt();
+ void InvokeInterruptCallback();
+
// This provides an asynchronous read of the stack limits for the current
// thread. There are no locks protecting this, but it is assumed that you
// have the global V8 lock if you are using multiple V8 threads.
@@ -307,6 +313,9 @@
int nesting_;
int postpone_interrupts_nesting_;
int interrupt_flags_;
+
+ InterruptCallback interrupt_callback_;
+ void* interrupt_callback_data_;
};
// TODO(isolates): Technically this could be calculated directly from a
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 1230801..7489df7 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -534,8 +534,8 @@
"trace progress of the incremental marking")
DEFINE_bool(track_gc_object_stats, false,
"track object counts and memory usage")
-DEFINE_bool(parallel_sweeping, true, "enable parallel sweeping")
-DEFINE_bool(concurrent_sweeping, false, "enable concurrent sweeping")
+DEFINE_bool(parallel_sweeping, false, "enable parallel sweeping")
+DEFINE_bool(concurrent_sweeping, true, "enable concurrent sweeping")
DEFINE_int(sweeper_threads, 0,
"number of parallel and concurrent sweeping threads")
#ifdef VERIFY_HEAP
diff --git a/src/heap-snapshot-generator-inl.h b/src/heap-snapshot-generator-inl.h
index 43002d2..582de32 100644
--- a/src/heap-snapshot-generator-inl.h
+++ b/src/heap-snapshot-generator-inl.h
@@ -59,7 +59,10 @@
HeapGraphEdge** HeapEntry::children_arr() {
ASSERT(children_index_ >= 0);
- return &snapshot_->children()[children_index_];
+ SLOW_ASSERT(children_index_ < snapshot_->children().length() ||
+ (children_index_ == snapshot_->children().length() &&
+ children_count_ == 0));
+ return &snapshot_->children().first() + children_index_;
}
diff --git a/src/heap.cc b/src/heap.cc
index c42c445..7477450 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -49,6 +49,7 @@
#include "snapshot.h"
#include "store-buffer.h"
#include "utils/random-number-generator.h"
+#include "v8conversions.h"
#include "v8threads.h"
#include "v8utils.h"
#include "vm-state-inl.h"
@@ -3689,6 +3690,7 @@
}
}
+
Heap::RootListIndex Heap::RootIndexForEmptyExternalArray(
ElementsKind elementsKind) {
switch (elementsKind) {
@@ -3723,16 +3725,11 @@
}
-
-
MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) {
// We need to distinguish the minus zero value and this cannot be
// done after conversion to int. Doing this by comparing bit
// patterns is faster than using fpclassify() et al.
- static const DoubleRepresentation minus_zero(-0.0);
-
- DoubleRepresentation rep(value);
- if (rep.bits == minus_zero.bits) {
+ if (IsMinusZero(value)) {
return AllocateHeapNumber(-0.0, pretenure);
}
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
index bbd3042..ae11042 100644
--- a/src/hydrogen-check-elimination.cc
+++ b/src/hydrogen-check-elimination.cc
@@ -127,9 +127,14 @@
new_entry->check_ = NULL;
new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
}
- if (succ->predecessors()->length() == 1) {
- HControlInstruction* end = succ->predecessors()->at(0)->end();
- if (end->IsCompareMap() && end->SuccessorAt(0) == succ) {
+ copy->cursor_ = cursor_;
+ copy->size_ = size_;
+
+ // Branch-sensitive analysis for certain comparisons may add more facts
+ // to the state for the successor on the true branch.
+ HControlInstruction* end = succ->predecessors()->at(0)->end();
+ if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) {
+ if (end->IsCompareMap()) {
// Learn on the true branch of if(CompareMap(x)).
HCompareMap* cmp = HCompareMap::cast(end);
HValue* object = cmp->value()->ActualValue();
@@ -141,9 +146,29 @@
list->Add(cmp->map(), phase_->zone());
entry->maps_ = list;
}
+ } else if (end->IsCompareObjectEqAndBranch()) {
+ // Learn on the true branch of if(CmpObjectEq(x, y)).
+ HCompareObjectEqAndBranch* cmp =
+ HCompareObjectEqAndBranch::cast(end);
+ HValue* left = cmp->left()->ActualValue();
+ HValue* right = cmp->right()->ActualValue();
+ HCheckTableEntry* le = copy->Find(left);
+ HCheckTableEntry* re = copy->Find(right);
+ if (le == NULL) {
+ if (re != NULL) {
+ copy->Insert(left, NULL, re->maps_->Copy(zone));
+ }
+ } else if (re == NULL) {
+ copy->Insert(right, NULL, le->maps_->Copy(zone));
+ } else {
+ MapSet intersect = le->maps_->Intersect(re->maps_, zone);
+ le->maps_ = intersect;
+ re->maps_ = intersect->Copy(zone);
+ }
}
- // TODO(titzer): is it worthwhile to learn on false branch too?
+ // Learning on false branches requires storing negative facts.
}
+
return copy;
}
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 46893e8..6e17397 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1377,7 +1377,7 @@
HConstant* c = HConstant::cast(value);
if (c->HasNumberValue()) {
double double_res = c->DoubleValue();
- if (TypeInfo::IsInt32Double(double_res)) {
+ if (IsInt32Double(double_res)) {
return HConstant::New(zone, context,
static_cast<int32_t>(double_res),
required_representation);
@@ -3794,7 +3794,7 @@
HConstant* c_right = HConstant::cast(right); \
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \
- if (TypeInfo::IsInt32Double(double_res)) { \
+ if (IsInt32Double(double_res)) { \
return H_CONSTANT_INT(double_res); \
} \
return H_CONSTANT_DOUBLE(double_res); \
@@ -3990,7 +3990,7 @@
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
if (c_right->DoubleValue() != 0) {
double double_res = c_left->DoubleValue() / c_right->DoubleValue();
- if (TypeInfo::IsInt32Double(double_res)) {
+ if (IsInt32Double(double_res)) {
return H_CONSTANT_INT(double_res);
}
return H_CONSTANT_DOUBLE(double_res);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index fde3abc..1e270ab 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1245,7 +1245,7 @@
virtual void Verify() V8_OVERRIDE;
#endif
- virtual bool IsCall() { return false; }
+ virtual bool HasStackCheck() { return false; }
DECLARE_ABSTRACT_INSTRUCTION(Instruction)
@@ -2243,8 +2243,6 @@
return -argument_count();
}
- virtual bool IsCall() V8_FINAL V8_OVERRIDE { return true; }
-
private:
int argument_count_;
};
@@ -2300,6 +2298,9 @@
known_function_(known_function) {
formal_parameter_count_ = known_function.is_null()
? 0 : known_function->shared()->formal_parameter_count();
+ has_stack_check_ = !known_function.is_null() &&
+ (known_function->code()->kind() == Code::FUNCTION ||
+ known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
}
static HInvokeFunction* New(Zone* zone,
@@ -2316,15 +2317,21 @@
Handle<JSFunction> known_function() { return known_function_; }
int formal_parameter_count() const { return formal_parameter_count_; }
+ virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+ return has_stack_check_;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
private:
HInvokeFunction(HValue* context, HValue* function, int argument_count)
- : HBinaryCall(context, function, argument_count) {
+ : HBinaryCall(context, function, argument_count),
+ has_stack_check_(false) {
}
Handle<JSFunction> known_function_;
int formal_parameter_count_;
+ bool has_stack_check_;
};
@@ -2348,16 +2355,24 @@
return Representation::None();
}
+ virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+ return has_stack_check_;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
private:
HCallConstantFunction(Handle<JSFunction> function, int argument_count)
: HCall<0>(argument_count),
function_(function),
- formal_parameter_count_(function->shared()->formal_parameter_count()) {}
+ formal_parameter_count_(function->shared()->formal_parameter_count()),
+ has_stack_check_(
+ function->code()->kind() == Code::FUNCTION ||
+ function->code()->kind() == Code::OPTIMIZED_FUNCTION) {}
Handle<JSFunction> function_;
int formal_parameter_count_;
+ bool has_stack_check_;
};
@@ -2465,16 +2480,24 @@
return Representation::None();
}
+ virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+ return has_stack_check_;
+ }
+
DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
private:
HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
: HCall<0>(argument_count),
target_(target),
- formal_parameter_count_(target->shared()->formal_parameter_count()) { }
+ formal_parameter_count_(target->shared()->formal_parameter_count()),
+ has_stack_check_(
+ target->code()->kind() == Code::FUNCTION ||
+ target->code()->kind() == Code::OPTIMIZED_FUNCTION) {}
Handle<JSFunction> target_;
int formal_parameter_count_;
+ bool has_stack_check_;
};
diff --git a/src/hydrogen-load-elimination.cc b/src/hydrogen-load-elimination.cc
index f3b5748..f2e993b 100644
--- a/src/hydrogen-load-elimination.cc
+++ b/src/hydrogen-load-elimination.cc
@@ -43,7 +43,6 @@
class HFieldApproximation : public ZoneObject {
public: // Just a data blob.
HValue* object_;
- HLoadNamedField* last_load_;
HValue* last_value_;
HFieldApproximation* next_;
@@ -52,7 +51,6 @@
if (this == NULL) return NULL;
HFieldApproximation* copy = new(zone) HFieldApproximation();
copy->object_ = this->object_;
- copy->last_load_ = this->last_load_;
copy->last_value_ = this->last_value_;
copy->next_ = this->next_->Copy(zone);
return copy;
@@ -197,7 +195,6 @@
if (approx->last_value_ == NULL) {
// Load is not redundant. Fill out a new entry.
- approx->last_load_ = instr;
approx->last_value_ = instr;
return instr;
} else {
@@ -217,12 +214,14 @@
HValue* object = instr->object()->ActualValue();
HValue* value = instr->value();
- // Kill non-equivalent may-alias entries.
- KillFieldInternal(object, field, value);
if (instr->has_transition()) {
- // A transition store alters the map of the object.
- // TODO(titzer): remember the new map (a constant) for the object.
+ // A transition introduces a new field and alters the map of the object.
+ // Since the field in the object is new, it cannot alias existing entries.
+ // TODO(titzer): introduce a constant for the new map and remember it.
KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
+ } else {
+ // Kill non-equivalent may-alias entries.
+ KillFieldInternal(object, field, value);
}
HFieldApproximation* approx = FindOrCreate(object, field);
@@ -231,7 +230,6 @@
return NULL;
} else {
// The store is not redundant. Update the entry.
- approx->last_load_ = NULL;
approx->last_value_ = value;
return instr;
}
@@ -314,7 +312,6 @@
// Insert the entry at the head of the list.
approx->object_ = object;
- approx->last_load_ = NULL;
approx->last_value_ = NULL;
approx->next_ = fields_[field];
fields_[field] = approx;
@@ -397,7 +394,6 @@
PrintF(" field %d: ", i);
for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
PrintF("[o%d =", a->object_->id());
- if (a->last_load_ != NULL) PrintF(" L%d", a->last_load_->id());
if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
PrintF("] ");
}
diff --git a/src/hydrogen-sce.cc b/src/hydrogen-sce.cc
index a6995f6..70b0a0c 100644
--- a/src/hydrogen-sce.cc
+++ b/src/hydrogen-sce.cc
@@ -43,7 +43,7 @@
HBasicBlock* dominator = back_edge;
while (true) {
for (HInstructionIterator it(dominator); !it.Done(); it.Advance()) {
- if (it.Current()->IsCall()) {
+ if (it.Current()->HasStackCheck()) {
block->loop_information()->stack_check()->Eliminate();
break;
}
diff --git a/src/ic.cc b/src/ic.cc
index 25f875a..dd7df98 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -35,6 +35,7 @@
#include "ic-inl.h"
#include "runtime.h"
#include "stub-cache.h"
+#include "v8conversions.h"
namespace v8 {
namespace internal {
@@ -2674,7 +2675,7 @@
new_kind = SMI;
} else if (object->IsHeapNumber()) {
double value = Handle<HeapNumber>::cast(object)->value();
- new_kind = TypeInfo::IsInt32Double(value) ? INT32 : NUMBER;
+ new_kind = IsInt32Double(value) ? INT32 : NUMBER;
} else if (object->IsString() && op() == Token::ADD) {
new_kind = STRING;
}
diff --git a/src/ic.h b/src/ic.h
index fa7ed6d..d1d2b61 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -29,12 +29,14 @@
#define V8_IC_H_
#include "macro-assembler.h"
-#include "type-info.h"
namespace v8 {
namespace internal {
+const int kMaxKeyedPolymorphism = 4;
+
+
// IC_UTIL_LIST defines all utility functions called from generated
// inline caching code. The argument for the macro, ICU, is the function name.
#define IC_UTIL_LIST(ICU) \
@@ -296,6 +298,12 @@
};
+enum StringStubFeedback {
+ DEFAULT_STRING_STUB = 0,
+ STRING_INDEX_OUT_OF_BOUNDS = 1
+};
+
+
class CallICBase: public IC {
public:
// ExtraICState bits
diff --git a/src/isolate.h b/src/isolate.h
index 31a0af8..5c3bbb3 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1082,6 +1082,10 @@
bool IsDeferredHandle(Object** location);
#endif // DEBUG
+ int max_available_threads() const {
+ return max_available_threads_;
+ }
+
void set_max_available_threads(int value) {
max_available_threads_ = value;
}
diff --git a/src/default-platform.cc b/src/libplatform/default-platform.cc
similarity index 64%
copy from src/default-platform.cc
copy to src/libplatform/default-platform.cc
index ef3c4eb..1e21ca4 100644
--- a/src/default-platform.cc
+++ b/src/libplatform/default-platform.cc
@@ -25,24 +25,58 @@
// (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"
+#include <queue>
+
+// TODO(jochen): We should have our own version of checks.h.
+#include "../checks.h"
+// TODO(jochen): Why is cpu.h not in platform/?
+#include "../cpu.h"
+#include "worker-thread.h"
+
namespace v8 {
namespace internal {
-DefaultPlatform::DefaultPlatform() {}
+DefaultPlatform::DefaultPlatform()
+ : initialized_(false), thread_pool_size_(0) {}
-DefaultPlatform::~DefaultPlatform() {}
+DefaultPlatform::~DefaultPlatform() {
+ LockGuard<Mutex> guard(&lock_);
+ queue_.Terminate();
+ if (initialized_) {
+ for (std::vector<WorkerThread*>::iterator i = thread_pool_.begin();
+ i != thread_pool_.end(); ++i) {
+ delete *i;
+ }
+ }
+}
+
+
+void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
+ LockGuard<Mutex> guard(&lock_);
+ ASSERT(thread_pool_size >= 0);
+ if (thread_pool_size < 1)
+ thread_pool_size = CPU::NumberOfProcessorsOnline();
+ thread_pool_size_ = Max(Min(thread_pool_size, kMaxThreadPoolSize), 1);
+}
+
+
+void DefaultPlatform::EnsureInitialized() {
+ LockGuard<Mutex> guard(&lock_);
+ if (initialized_) return;
+ initialized_ = true;
+
+ for (int i = 0; i < thread_pool_size_; ++i)
+ thread_pool_.push_back(new WorkerThread(&queue_));
+}
void DefaultPlatform::CallOnBackgroundThread(Task *task,
ExpectedRuntime expected_runtime) {
- // TODO(jochen): implement.
- task->Run();
- delete task;
+ EnsureInitialized();
+ queue_.Append(task);
}
@@ -52,5 +86,4 @@
delete task;
}
-
} } // namespace v8::internal
diff --git a/src/default-platform.h b/src/libplatform/default-platform.h
similarity index 76%
rename from src/default-platform.h
rename to src/libplatform/default-platform.h
index fe1bf8e..877b3a6 100644
--- a/src/default-platform.h
+++ b/src/libplatform/default-platform.h
@@ -25,19 +25,31 @@
// (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_
+#ifndef V8_LIBPLATFORM_DEFAULT_PLATFORM_H_
+#define V8_LIBPLATFORM_DEFAULT_PLATFORM_H_
-#include "v8.h"
+#include <vector>
+
+#include "../../include/v8-platform.h"
+// TODO(jochen): We should have our own version of globals.h.
+#include "../globals.h"
+#include "../platform/mutex.h"
+#include "task-queue.h"
namespace v8 {
namespace internal {
+class TaskQueue;
+class Thread;
+class WorkerThread;
+
class DefaultPlatform : public Platform {
public:
DefaultPlatform();
virtual ~DefaultPlatform();
+ void SetThreadPoolSize(int thread_pool_size);
+
// v8::Platform implementation.
virtual void CallOnBackgroundThread(
Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
@@ -45,6 +57,16 @@
Task *task) V8_OVERRIDE;
private:
+ static const int kMaxThreadPoolSize = 4;
+
+ void EnsureInitialized();
+
+ Mutex lock_;
+ bool initialized_;
+ int thread_pool_size_;
+ std::vector<WorkerThread*> thread_pool_;
+ TaskQueue queue_;
+
DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
};
@@ -52,4 +74,4 @@
} } // namespace v8::internal
-#endif // V8_DEFAULT_PLATFORM_H_
+#endif // V8_LIBPLATFORM_DEFAULT_PLATFORM_H_
diff --git a/src/default-platform.cc b/src/libplatform/task-queue.cc
similarity index 62%
copy from src/default-platform.cc
copy to src/libplatform/task-queue.cc
index ef3c4eb..1ea31eb 100644
--- a/src/default-platform.cc
+++ b/src/libplatform/task-queue.cc
@@ -25,32 +25,56 @@
// (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 "task-queue.h"
-#include "default-platform.h"
+// TODO(jochen): We should have our own version of checks.h.
+#include "../checks.h"
namespace v8 {
namespace internal {
-
-DefaultPlatform::DefaultPlatform() {}
+TaskQueue::TaskQueue() : process_queue_semaphore_(0), terminated_(false) {}
-DefaultPlatform::~DefaultPlatform() {}
-
-void DefaultPlatform::CallOnBackgroundThread(Task *task,
- ExpectedRuntime expected_runtime) {
- // TODO(jochen): implement.
- task->Run();
- delete task;
+TaskQueue::~TaskQueue() {
+ LockGuard<Mutex> guard(&lock_);
+ ASSERT(terminated_);
+ ASSERT(task_queue_.empty());
}
-void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
- // TODO(jochen): implement.
- task->Run();
- delete task;
+void TaskQueue::Append(Task* task) {
+ LockGuard<Mutex> guard(&lock_);
+ ASSERT(!terminated_);
+ task_queue_.push(task);
+ process_queue_semaphore_.Signal();
}
+Task* TaskQueue::GetNext() {
+ for (;;) {
+ {
+ LockGuard<Mutex> guard(&lock_);
+ if (!task_queue_.empty()) {
+ Task* result = task_queue_.front();
+ task_queue_.pop();
+ return result;
+ }
+ if (terminated_) {
+ process_queue_semaphore_.Signal();
+ return NULL;
+ }
+ }
+ process_queue_semaphore_.Wait();
+ }
+}
+
+
+void TaskQueue::Terminate() {
+ LockGuard<Mutex> guard(&lock_);
+ ASSERT(!terminated_);
+ terminated_ = true;
+ process_queue_semaphore_.Signal();
+}
+
} } // namespace v8::internal
diff --git a/src/default-platform.h b/src/libplatform/task-queue.h
similarity index 68%
copy from src/default-platform.h
copy to src/libplatform/task-queue.h
index fe1bf8e..a3182d3 100644
--- a/src/default-platform.h
+++ b/src/libplatform/task-queue.h
@@ -25,31 +25,47 @@
// (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_
+#ifndef V8_LIBPLATFORM_TASK_QUEUE_H_
+#define V8_LIBPLATFORM_TASK_QUEUE_H_
-#include "v8.h"
+#include <queue>
+
+// TODO(jochen): We should have our own version of globals.h.
+#include "../globals.h"
+#include "../platform/mutex.h"
+#include "../platform/semaphore.h"
namespace v8 {
+
+class Task;
+
namespace internal {
-class DefaultPlatform : public Platform {
+class TaskQueue {
public:
- DefaultPlatform();
- virtual ~DefaultPlatform();
+ TaskQueue();
+ ~TaskQueue();
- // v8::Platform implementation.
- virtual void CallOnBackgroundThread(
- Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
- virtual void CallOnForegroundThread(v8::Isolate *isolate,
- Task *task) V8_OVERRIDE;
+ // Appends a task to the queue. The queue takes ownership of |task|.
+ void Append(Task* task);
+
+ // Returns the next task to process. Blocks if no task is available. Returns
+ // NULL if the queue is terminated.
+ Task* GetNext();
+
+ // Terminate the queue.
+ void Terminate();
private:
- DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
-};
+ Mutex lock_;
+ Semaphore process_queue_semaphore_;
+ std::queue<Task*> task_queue_;
+ bool terminated_;
+ DISALLOW_COPY_AND_ASSIGN(TaskQueue);
+};
} } // namespace v8::internal
-#endif // V8_DEFAULT_PLATFORM_H_
+#endif // V8_LIBPLATFORM_TASK_QUEUE_H_
diff --git a/src/default-platform.cc b/src/libplatform/worker-thread.cc
similarity index 77%
rename from src/default-platform.cc
rename to src/libplatform/worker-thread.cc
index ef3c4eb..cca8a97 100644
--- a/src/default-platform.cc
+++ b/src/libplatform/worker-thread.cc
@@ -25,32 +25,32 @@
// (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 "worker-thread.h"
-#include "default-platform.h"
+// TODO(jochen): We should have our own version of checks.h.
+#include "../checks.h"
+#include "../../include/v8-platform.h"
+#include "task-queue.h"
namespace v8 {
namespace internal {
-
-DefaultPlatform::DefaultPlatform() {}
-
-
-DefaultPlatform::~DefaultPlatform() {}
-
-void DefaultPlatform::CallOnBackgroundThread(Task *task,
- ExpectedRuntime expected_runtime) {
- // TODO(jochen): implement.
- task->Run();
- delete task;
+WorkerThread::WorkerThread(TaskQueue* queue)
+ : Thread("V8 WorkerThread"), queue_(queue) {
+ Start();
}
-void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
- // TODO(jochen): implement.
- task->Run();
- delete task;
+WorkerThread::~WorkerThread() {
+ Join();
}
+void WorkerThread::Run() {
+ while (Task* task = queue_->GetNext()) {
+ task->Run();
+ delete task;
+ }
+}
+
} } // namespace v8::internal
diff --git a/src/default-platform.h b/src/libplatform/worker-thread.h
similarity index 75%
copy from src/default-platform.h
copy to src/libplatform/worker-thread.h
index fe1bf8e..f0b9019 100644
--- a/src/default-platform.h
+++ b/src/libplatform/worker-thread.h
@@ -25,31 +25,38 @@
// (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_
+#ifndef V8_LIBPLATFORM_WORKER_THREAD_H_
+#define V8_LIBPLATFORM_WORKER_THREAD_H_
-#include "v8.h"
+#include <queue>
+
+// TODO(jochen): We should have our own version of globals.h.
+#include "../globals.h"
+#include "../platform.h"
namespace v8 {
+
namespace internal {
-class DefaultPlatform : public Platform {
- public:
- DefaultPlatform();
- virtual ~DefaultPlatform();
+class TaskQueue;
- // v8::Platform implementation.
- virtual void CallOnBackgroundThread(
- Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
- virtual void CallOnForegroundThread(v8::Isolate *isolate,
- Task *task) V8_OVERRIDE;
+class WorkerThread : public Thread {
+ public:
+ explicit WorkerThread(TaskQueue* queue);
+ virtual ~WorkerThread();
+
+ // Thread implementation.
+ virtual void Run() V8_OVERRIDE;
private:
- DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
-};
+ friend class QuitTask;
+ TaskQueue* queue_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerThread);
+};
} } // namespace v8::internal
-#endif // V8_DEFAULT_PLATFORM_H_
+#endif // V8_LIBPLATFORM_WORKER_THREAD_H_
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 40cc99f..ae8e3e7 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -825,7 +825,7 @@
(a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
FrameScope scope(masm, StackFrame::MANUAL);
__ MultiPush(saved_regs);
- __ PrepareCallCFunction(1, 0, a2);
+ __ PrepareCallCFunction(2, 0, a2);
__ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
__ CallCFunction(
ExternalReference::get_make_code_young_function(masm->isolate()), 2);
@@ -864,7 +864,7 @@
(a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
FrameScope scope(masm, StackFrame::MANUAL);
__ MultiPush(saved_regs);
- __ PrepareCallCFunction(1, 0, a2);
+ __ PrepareCallCFunction(2, 0, a2);
__ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
__ CallCFunction(
ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index bc981cb..4e3ab32 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -1228,12 +1228,12 @@
void MacroAssembler::Move(FPURegister dst, double imm) {
static const DoubleRepresentation minus_zero(-0.0);
static const DoubleRepresentation zero(0.0);
- DoubleRepresentation value(imm);
+ DoubleRepresentation value_rep(imm);
// Handle special values first.
bool force_load = dst.is(kDoubleRegZero);
- if (value.bits == zero.bits && !force_load) {
+ if (value_rep == zero && !force_load) {
mov_d(dst, kDoubleRegZero);
- } else if (value.bits == minus_zero.bits && !force_load) {
+ } else if (value_rep == minus_zero && !force_load) {
neg_d(dst, kDoubleRegZero);
} else {
uint32_t lo, hi;
diff --git a/src/property-details.h b/src/property-details.h
index 617e9b2..753eeee 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -113,8 +113,6 @@
static Representation FromKind(Kind kind) { return Representation(kind); }
- // TODO(rossberg): this should die eventually.
- static Representation FromType(TypeInfo info);
static Representation FromType(Handle<Type> type);
bool Equals(const Representation& other) const {
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 6e68314..dc2c340 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -35,6 +35,7 @@
#include "gdb-jit.h"
#include "ic-inl.h"
#include "stub-cache.h"
+#include "type-info.h"
#include "vm-state-inl.h"
namespace v8 {
diff --git a/src/type-info.cc b/src/type-info.cc
index 73d8c75..3cdcf8e 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -42,20 +42,6 @@
namespace internal {
-TypeInfo TypeInfo::FromValue(Handle<Object> value) {
- if (value->IsSmi()) {
- return TypeInfo::Smi();
- } else if (value->IsHeapNumber()) {
- return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
- ? TypeInfo::Integer32()
- : TypeInfo::Double();
- } else if (value->IsString()) {
- return TypeInfo::String();
- }
- return TypeInfo::Unknown();
-}
-
-
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
Handle<Context> native_context,
Isolate* isolate,
@@ -586,14 +572,4 @@
}
-Representation Representation::FromType(TypeInfo info) {
- if (info.IsUninitialized()) return Representation::None();
- if (info.IsSmi()) return Representation::Smi();
- if (info.IsInteger32()) return Representation::Integer32();
- if (info.IsDouble()) return Representation::Double();
- if (info.IsNumber()) return Representation::Double();
- return Representation::Tagged();
-}
-
-
} } // namespace v8::internal
diff --git a/src/type-info.h b/src/type-info.h
index 8bad5c0..635be1a 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -36,189 +36,7 @@
namespace v8 {
namespace internal {
-const int kMaxKeyedPolymorphism = 4;
-
-// Unknown
-// | \____________
-// | |
-// Primitive Non-primitive
-// | \_______ |
-// | | |
-// Number String |
-// / \ | |
-// Double Integer32 | /
-// | | / /
-// | Smi / /
-// | | / __/
-// Uninitialized.
-
-class TypeInfo {
- public:
- TypeInfo() : type_(kUninitialized) { }
-
- static TypeInfo Unknown() { return TypeInfo(kUnknown); }
- // We know it's a primitive type.
- static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
- // We know it's a number of some sort.
- static TypeInfo Number() { return TypeInfo(kNumber); }
- // We know it's a signed 32 bit integer.
- static TypeInfo Integer32() { return TypeInfo(kInteger32); }
- // We know it's a Smi.
- static TypeInfo Smi() { return TypeInfo(kSmi); }
- // We know it's a heap number.
- static TypeInfo Double() { return TypeInfo(kDouble); }
- // We know it's a string.
- static TypeInfo String() { return TypeInfo(kString); }
- // We know it's an internalized string.
- static TypeInfo InternalizedString() { return TypeInfo(kInternalizedString); }
- // We know it's a non-primitive (object) type.
- static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
- // We haven't started collecting info yet.
- static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
-
- int ToInt() {
- return type_;
- }
-
- static TypeInfo FromInt(int bit_representation) {
- Type t = static_cast<Type>(bit_representation);
- ASSERT(t == kUnknown ||
- t == kPrimitive ||
- t == kNumber ||
- t == kInteger32 ||
- t == kSmi ||
- t == kDouble ||
- t == kString ||
- t == kNonPrimitive);
- return TypeInfo(t);
- }
-
- // Return the weakest (least precise) common type.
- static TypeInfo Combine(TypeInfo a, TypeInfo b) {
- return TypeInfo(static_cast<Type>(a.type_ & b.type_));
- }
-
-
- // Integer32 is an integer that can be represented as a signed
- // 32-bit integer. It has to be
- // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
- // as it is not an Integer32.
- static inline bool IsInt32Double(double value) {
- const DoubleRepresentation minus_zero(-0.0);
- DoubleRepresentation rep(value);
- if (rep.bits == minus_zero.bits) return false;
- if (value >= kMinInt && value <= kMaxInt &&
- value == static_cast<int32_t>(value)) {
- return true;
- }
- return false;
- }
-
- static TypeInfo FromValue(Handle<Object> value);
-
- bool Equals(const TypeInfo& other) {
- return type_ == other.type_;
- }
-
- inline bool IsUnknown() {
- ASSERT(type_ != kUninitialized);
- return type_ == kUnknown;
- }
-
- inline bool IsPrimitive() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kPrimitive) == kPrimitive);
- }
-
- inline bool IsNumber() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kNumber) == kNumber);
- }
-
- inline bool IsSmi() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kSmi) == kSmi);
- }
-
- inline bool IsInternalizedString() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kInternalizedString) == kInternalizedString);
- }
-
- inline bool IsNonInternalizedString() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kInternalizedString) == kString);
- }
-
- inline bool IsInteger32() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kInteger32) == kInteger32);
- }
-
- inline bool IsDouble() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kDouble) == kDouble);
- }
-
- inline bool IsString() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kString) == kString);
- }
-
- inline bool IsNonPrimitive() {
- ASSERT(type_ != kUninitialized);
- return ((type_ & kNonPrimitive) == kNonPrimitive);
- }
-
- inline bool IsUninitialized() {
- return type_ == kUninitialized;
- }
-
- const char* ToString() {
- switch (type_) {
- case kUnknown: return "Unknown";
- case kPrimitive: return "Primitive";
- case kNumber: return "Number";
- case kInteger32: return "Integer32";
- case kSmi: return "Smi";
- case kInternalizedString: return "InternalizedString";
- case kDouble: return "Double";
- case kString: return "String";
- case kNonPrimitive: return "Object";
- case kUninitialized: return "Uninitialized";
- }
- UNREACHABLE();
- return "Unreachable code";
- }
-
- private:
- enum Type {
- kUnknown = 0, // 0000000
- kPrimitive = 0x10, // 0010000
- kNumber = 0x11, // 0010001
- kInteger32 = 0x13, // 0010011
- kSmi = 0x17, // 0010111
- kDouble = 0x19, // 0011001
- kString = 0x30, // 0110000
- kInternalizedString = 0x32, // 0110010
- kNonPrimitive = 0x40, // 1000000
- kUninitialized = 0x7f // 1111111
- };
-
- explicit inline TypeInfo(Type t) : type_(t) { }
-
- Type type_;
-};
-
-
-enum StringStubFeedback {
- DEFAULT_STRING_STUB = 0,
- STRING_INDEX_OUT_OF_BOUNDS = 1
-};
-
-
// Forward declarations.
-class CompilationInfo;
class ICStub;
class SmallMapList;
diff --git a/src/unique.h b/src/unique.h
index a93b046..a2f29e4 100644
--- a/src/unique.h
+++ b/src/unique.h
@@ -278,7 +278,7 @@
return out;
}
- // Makes an exact copy of this set. O(|this| + |that|).
+ // Makes an exact copy of this set. O(|this|).
UniqueSet<T>* Copy(Zone* zone) const {
UniqueSet<T>* copy = new(zone) UniqueSet<T>();
copy->size_ = this->size_;
diff --git a/src/v8.cc b/src/v8.cc
index 265f0a6..76a6cb7 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -32,13 +32,13 @@
#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"
#include "hydrogen.h"
+#ifdef V8_USE_DEFAULT_PLATFORM
+#include "libplatform/default-platform.h"
+#endif
#include "lithium-allocator.h"
#include "objects.h"
#include "once.h"
@@ -79,6 +79,11 @@
if (isolate->IsDead()) return false;
if (isolate->IsInitialized()) return true;
+#ifdef V8_USE_DEFAULT_PLATFORM
+ DefaultPlatform* platform = static_cast<DefaultPlatform*>(platform_);
+ platform->SetThreadPoolSize(isolate->max_available_threads());
+#endif
+
return isolate->Init(des);
}
diff --git a/src/v8conversions.h b/src/v8conversions.h
index 68107de..f2568c0 100644
--- a/src/v8conversions.h
+++ b/src/v8conversions.h
@@ -33,6 +33,24 @@
namespace v8 {
namespace internal {
+
+static inline bool IsMinusZero(double value) {
+ static const DoubleRepresentation minus_zero(-0.0);
+ return DoubleRepresentation(value) == minus_zero;
+}
+
+
+// Integer32 is an integer that can be represented as a signed 32-bit
+// integer. It has to be in the range [-2^31, 2^31 - 1].
+// We also have to check for negative 0 as it is not an Integer32.
+static inline bool IsInt32Double(double value) {
+ return !IsMinusZero(value) &&
+ value >= kMinInt &&
+ value <= kMaxInt &&
+ value == FastI2D(FastD2I(value));
+}
+
+
// Convert from Number object to C integer.
inline int32_t NumberToInt32(Object* number) {
if (number->IsSmi()) return Smi::cast(number)->value();
diff --git a/src/v8globals.h b/src/v8globals.h
index 4910cb7..a9980e5 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -322,6 +322,9 @@
double value;
int64_t bits;
DoubleRepresentation(double x) { value = x; }
+ bool operator==(const DoubleRepresentation& other) const {
+ return bits == other.bits;
+ }
};
diff --git a/src/version.cc b/src/version.cc
index 37f29c5..eb320a9 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 24
-#define BUILD_NUMBER 5
+#define BUILD_NUMBER 6
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index aef9164..f2c955c 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -604,9 +604,9 @@
__ movq(arg_reg_1, Operand(rsp, kNumSafepointRegisters * kPointerSize));
{ // NOLINT
FrameScope scope(masm, StackFrame::MANUAL);
- __ PrepareCallCFunction(1);
+ __ PrepareCallCFunction(2);
__ CallCFunction(
- ExternalReference::get_make_code_young_function(masm->isolate()), 1);
+ ExternalReference::get_make_code_young_function(masm->isolate()), 2);
}
__ Popad();
__ ret(0);
@@ -637,10 +637,10 @@
__ subq(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength));
{ // NOLINT
FrameScope scope(masm, StackFrame::MANUAL);
- __ PrepareCallCFunction(1);
+ __ PrepareCallCFunction(2);
__ CallCFunction(
ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
- 1);
+ 2);
}
__ Popad();
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index 3c5666e..6586a27 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -29,7 +29,6 @@
#define V8_X64_CODE_STUBS_X64_H_
#include "ic-inl.h"
-#include "type-info.h"
namespace v8 {
namespace internal {