summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps/v8/.gitignore2
-rw-r--r--deps/v8/AUTHORS1
-rw-r--r--deps/v8/ChangeLog17
-rw-r--r--deps/v8/include/v8.h2
-rw-r--r--deps/v8/src/accessors.cc83
-rw-r--r--deps/v8/src/api.cc36
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc314
-rw-r--r--deps/v8/src/arm/code-stubs-arm.h5
-rw-r--r--deps/v8/src/arm/codegen-arm.cc10
-rw-r--r--deps/v8/src/arm/deoptimizer-arm.cc33
-rw-r--r--deps/v8/src/arm/full-codegen-arm.cc6
-rw-r--r--deps/v8/src/arm/jump-target-arm.cc10
-rw-r--r--deps/v8/src/arm/lithium-arm.cc15
-rw-r--r--deps/v8/src/arm/lithium-arm.h4
-rw-r--r--deps/v8/src/arm/lithium-codegen-arm.cc58
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc13
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h11
-rw-r--r--deps/v8/src/arm/virtual-frame-arm.cc4
-rw-r--r--deps/v8/src/array.js14
-rw-r--r--deps/v8/src/assembler.cc4
-rw-r--r--deps/v8/src/ast.cc37
-rw-r--r--deps/v8/src/bootstrapper.cc1
-rw-r--r--deps/v8/src/builtins.cc42
-rw-r--r--deps/v8/src/deoptimizer.cc38
-rw-r--r--deps/v8/src/deoptimizer.h17
-rw-r--r--deps/v8/src/factory.cc18
-rw-r--r--deps/v8/src/factory.h9
-rw-r--r--deps/v8/src/gdb-jit.cc374
-rw-r--r--deps/v8/src/gdb-jit.h4
-rw-r--r--deps/v8/src/hashmap.h3
-rw-r--r--deps/v8/src/heap.cc32
-rw-r--r--deps/v8/src/heap.h14
-rw-r--r--deps/v8/src/hydrogen-instructions.cc1
-rw-r--r--deps/v8/src/hydrogen-instructions.h31
-rw-r--r--deps/v8/src/hydrogen.cc40
-rw-r--r--deps/v8/src/hydrogen.h1
-rw-r--r--deps/v8/src/ia32/code-stubs-ia32.cc12
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc12
-rw-r--r--deps/v8/src/ia32/deoptimizer-ia32.cc175
-rw-r--r--deps/v8/src/ia32/lithium-codegen-ia32.cc55
-rw-r--r--deps/v8/src/ia32/lithium-ia32.cc18
-rw-r--r--deps/v8/src/ia32/lithium-ia32.h4
-rw-r--r--deps/v8/src/lithium-allocator.cc11
-rw-r--r--deps/v8/src/messages.cc82
-rw-r--r--deps/v8/src/messages.h11
-rw-r--r--deps/v8/src/messages.js244
-rw-r--r--deps/v8/src/mirror-debugger.js4
-rw-r--r--deps/v8/src/objects-debug.cc16
-rw-r--r--deps/v8/src/objects-inl.h55
-rw-r--r--deps/v8/src/objects-printer.cc22
-rw-r--r--deps/v8/src/objects-visiting.cc1
-rw-r--r--deps/v8/src/objects.cc4
-rw-r--r--deps/v8/src/objects.h70
-rw-r--r--deps/v8/src/parser.cc9
-rw-r--r--deps/v8/src/runtime.cc39
-rw-r--r--deps/v8/src/runtime.h7
-rw-r--r--deps/v8/src/safepoint-table.cc11
-rw-r--r--deps/v8/src/safepoint-table.h11
-rw-r--r--deps/v8/src/scanner-base.cc10
-rw-r--r--deps/v8/src/scanner-base.h2
-rw-r--r--deps/v8/src/utils.h32
-rw-r--r--deps/v8/src/version.cc6
-rw-r--r--deps/v8/src/x64/codegen-x64.cc12
-rw-r--r--deps/v8/src/x64/deoptimizer-x64.cc28
-rw-r--r--deps/v8/src/x64/lithium-codegen-x64.cc16
-rw-r--r--deps/v8/src/x64/lithium-x64.cc15
-rw-r--r--deps/v8/src/x64/lithium-x64.h4
-rw-r--r--deps/v8/test/cctest/cctest.status8
-rw-r--r--deps/v8/test/cctest/test-api.cc25
-rw-r--r--deps/v8/test/cctest/test-log.cc15
-rw-r--r--deps/v8/test/mjsunit/array-splice.js14
-rw-r--r--deps/v8/test/mjsunit/compiler/literals.js3
-rw-r--r--deps/v8/test/mjsunit/compiler/regress-1085.js35
-rw-r--r--deps/v8/test/mjsunit/math-pow.js45
-rw-r--r--deps/v8/test/mjsunit/mirror-error.js2
-rw-r--r--deps/v8/test/mjsunit/regress/regress-1079.js45
-rw-r--r--deps/v8/test/mjsunit/regress/regress-3408144.js37
-rw-r--r--deps/v8/test/mjsunit/regress/regress-71647.js34
-rw-r--r--deps/v8/test/mjsunit/strict-mode.js188
-rw-r--r--deps/v8/tools/v8.xcodeproj/project.pbxproj6
80 files changed, 1898 insertions, 861 deletions
diff --git a/deps/v8/.gitignore b/deps/v8/.gitignore
index 974628d88..d85ef64d4 100644
--- a/deps/v8/.gitignore
+++ b/deps/v8/.gitignore
@@ -20,6 +20,8 @@ d8_g
shell
shell_g
/obj/
+/tools/oom_dump/oom_dump
+/tools/oom_dump/oom_dump.o
/tools/visual_studio/Debug
/tools/visual_studio/Release
/xcodebuild/
diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS
index eedf840c5..da864885a 100644
--- a/deps/v8/AUTHORS
+++ b/deps/v8/AUTHORS
@@ -32,6 +32,7 @@ Rafal Krypa <rafal@krypa.net>
Rene Rebe <rene@exactcode.de>
Rodolph Perfetta <rodolph.perfetta@arm.com>
Ryan Dahl <coldredlemur@gmail.com>
+Sanjoy Das <sanjoy@playingwithpointers.com>
Subrato K De <subratokde@codeaurora.org>
Vlad Burlik <vladbph@gmail.com>
Mike Gilbert <floppymaster@gmail.com>
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index 0e1ccda1e..f143a40cd 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,4 +1,19 @@
-2011-01=31: Version 3.1.0
+2011-02-02: Version 3.1.1
+
+ Perform security checks before fetching the value in
+ Object.getOwnPropertyDescriptor.
+
+ Fixed a bug in Array.prototype.splice triggered by passing no
+ arguments.
+
+ Fixed bugs in -0 in arithmetic and in Math.pow.
+
+ Fixed bugs in the register allocator and in switching from optimized
+ to unoptimized code.
+
+
+2011-01-31: Version 3.1.0
+
Performance improvements on all platforms.
diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h
index 44a7dcc89..44ff2c00e 100644
--- a/deps/v8/include/v8.h
+++ b/deps/v8/include/v8.h
@@ -3448,7 +3448,7 @@ class Internals {
static const int kFullStringRepresentationMask = 0x07;
static const int kExternalTwoByteRepresentationTag = 0x02;
- static const int kJSObjectType = 0x9f;
+ static const int kJSObjectType = 0xa0;
static const int kFirstNonstringType = 0x80;
static const int kProxyType = 0x85;
diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc
index c7d9cfe94..2b205d5d7 100644
--- a/deps/v8/src/accessors.cc
+++ b/deps/v8/src/accessors.cc
@@ -675,46 +675,36 @@ static void ComputeSlotMappingForArguments(JavaScriptFrame* frame,
int inlined_frame_index,
Vector<SlotRef>* args_slots) {
AssertNoAllocation no_gc;
-
int deopt_index = AstNode::kNoNumber;
-
DeoptimizationInputData* data =
static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
-
TranslationIterator it(data->TranslationByteArray(),
data->TranslationIndex(deopt_index)->value());
-
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
ASSERT(opcode == Translation::BEGIN);
int frame_count = it.Next();
-
USE(frame_count);
ASSERT(frame_count > inlined_frame_index);
-
int frames_to_skip = inlined_frame_index;
while (true) {
opcode = static_cast<Translation::Opcode>(it.Next());
-
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
-
if (opcode == Translation::FRAME) {
if (frames_to_skip == 0) {
- // We reached frame corresponding to inlined function in question.
- // Process translation commands for arguments.
-
- // Skip translation command for receiver.
+ // We reached the frame corresponding to the inlined function
+ // in question. Process the translation commands for the
+ // arguments.
+ //
+ // Skip the translation command for the receiver.
it.Skip(Translation::NumberOfOperandsFor(
static_cast<Translation::Opcode>(it.Next())));
-
// Compute slots for arguments.
for (int i = 0; i < args_slots->length(); ++i) {
(*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame);
}
-
return;
}
-
frames_to_skip--;
}
}
@@ -727,16 +717,11 @@ static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
JavaScriptFrame* frame,
Handle<JSFunction> inlined_function,
int inlined_frame_index) {
-
int args_count = inlined_function->shared()->formal_parameter_count();
-
ScopedVector<SlotRef> args_slots(args_count);
-
ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots);
-
Handle<JSObject> arguments =
Factory::NewArgumentsObject(inlined_function, args_count);
-
Handle<FixedArray> array = Factory::NewFixedArray(args_count);
for (int i = 0; i < args_count; ++i) {
Handle<Object> value = args_slots[i].GetValue();
@@ -766,39 +751,43 @@ MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
if (functions[i] != *function) continue;
if (i > 0) {
- // Function in question was inlined.
+ // The function in question was inlined. Inlined functions have the
+ // correct number of arguments and no allocated arguments object, so
+ // we can construct a fresh one by interpreting the function's
+ // deoptimization input data.
return ConstructArgumentsObjectForInlinedFunction(frame, function, i);
- } else {
+ }
+
+ if (!frame->is_optimized()) {
// If there is an arguments variable in the stack, we return that.
- int index = function->shared()->scope_info()->
- StackSlotIndex(Heap::arguments_symbol());
+ Handle<SerializedScopeInfo> info(function->shared()->scope_info());
+ int index = info->StackSlotIndex(Heap::arguments_symbol());
if (index >= 0) {
- Handle<Object> arguments =
- Handle<Object>(frame->GetExpression(index));
+ Handle<Object> arguments(frame->GetExpression(index));
if (!arguments->IsArgumentsMarker()) return *arguments;
}
-
- // If there isn't an arguments variable in the stack, we need to
- // find the frame that holds the actual arguments passed to the
- // function on the stack.
- it.AdvanceToArgumentsFrame();
- frame = it.frame();
-
- // Get the number of arguments and construct an arguments object
- // mirror for the right frame.
- const int length = frame->GetProvidedParametersCount();
- Handle<JSObject> arguments = Factory::NewArgumentsObject(function,
- length);
- Handle<FixedArray> array = Factory::NewFixedArray(length);
-
- // Copy the parameters to the arguments object.
- ASSERT(array->length() == length);
- for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
- arguments->set_elements(*array);
-
- // Return the freshly allocated arguments object.
- return *arguments;
}
+
+ // If there is no arguments variable in the stack or we have an
+ // optimized frame, we find the frame that holds the actual arguments
+ // passed to the function.
+ it.AdvanceToArgumentsFrame();
+ frame = it.frame();
+
+ // Get the number of arguments and construct an arguments object
+ // mirror for the right frame.
+ const int length = frame->GetProvidedParametersCount();
+ Handle<JSObject> arguments = Factory::NewArgumentsObject(function,
+ length);
+ Handle<FixedArray> array = Factory::NewFixedArray(length);
+
+ // Copy the parameters to the arguments object.
+ ASSERT(array->length() == length);
+ for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
+ arguments->set_elements(*array);
+
+ // Return the freshly allocated arguments object.
+ return *arguments;
}
functions.Rewind(0);
}
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index 93037822c..c16244038 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -1478,11 +1478,11 @@ v8::Handle<Value> Message::GetScriptResourceName() const {
}
ENTER_V8;
HandleScope scope;
- i::Handle<i::JSObject> obj =
- i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+ i::Handle<i::JSMessageObject> message =
+ i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
// Return this.script.name.
i::Handle<i::JSValue> script =
- i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+ i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
return scope.Close(Utils::ToLocal(resource_name));
}
@@ -1494,11 +1494,11 @@ v8::Handle<Value> Message::GetScriptData() const {
}
ENTER_V8;
HandleScope scope;
- i::Handle<i::JSObject> obj =
- i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+ i::Handle<i::JSMessageObject> message =
+ i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
// Return this.script.data.
i::Handle<i::JSValue> script =
- i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+ i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
i::Handle<i::Object> data(i::Script::cast(script->value())->data());
return scope.Close(Utils::ToLocal(data));
}
@@ -1510,9 +1510,9 @@ v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
}
ENTER_V8;
HandleScope scope;
- i::Handle<i::JSObject> obj =
- i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
- i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
+ i::Handle<i::JSMessageObject> message =
+ i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+ i::Handle<i::Object> stackFramesObj(message->stack_frames());
if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
i::Handle<i::JSArray> stackTrace =
i::Handle<i::JSArray>::cast(stackFramesObj);
@@ -1552,6 +1552,7 @@ int Message::GetLineNumber() const {
ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
ENTER_V8;
HandleScope scope;
+
EXCEPTION_PREAMBLE();
i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
Utils::OpenHandle(this),
@@ -1565,9 +1566,9 @@ int Message::GetStartPosition() const {
if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
ENTER_V8;
HandleScope scope;
-
- i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
- return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
+ i::Handle<i::JSMessageObject> message =
+ i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+ return message->start_position();
}
@@ -1575,8 +1576,9 @@ int Message::GetEndPosition() const {
if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
ENTER_V8;
HandleScope scope;
- i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
- return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
+ i::Handle<i::JSMessageObject> message =
+ i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+ return message->end_position();
}
@@ -1606,8 +1608,10 @@ int Message::GetEndColumn() const {
data_obj,
&has_pending_exception);
EXCEPTION_BAILOUT_CHECK(0);
- int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
- int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
+ i::Handle<i::JSMessageObject> message =
+ i::Handle<i::JSMessageObject>::cast(data_obj);
+ int start = message->start_position();
+ int end = message->end_position();
return static_cast<int>(start_col_obj->Number()) + (end - start);
}
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index 0a1ffbda5..590d8ce15 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -389,7 +389,7 @@ class FloatingPointHelper : public AllStatic {
// floating point registers VFP3 must be supported. If core registers are
// requested when VFP3 is supported d6 and d7 will still be scratched. If
// either r0 or r1 is not a number (not smi and not heap number object) the
- // not_number label is jumped to.
+ // not_number label is jumped to with r0 and r1 intact.
static void LoadOperands(MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register heap_number_map,
@@ -417,11 +417,11 @@ void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(VFP3);
__ mov(scratch1, Operand(r0, ASR, kSmiTagSize));
- __ vmov(s15, scratch1);
- __ vcvt_f64_s32(d7, s15);
+ __ vmov(d7.high(), scratch1);
+ __ vcvt_f64_s32(d7, d7.high());
__ mov(scratch1, Operand(r1, ASR, kSmiTagSize));
- __ vmov(s13, scratch1);
- __ vcvt_f64_s32(d6, s13);
+ __ vmov(d6.high(), scratch1);
+ __ vcvt_f64_s32(d6, d6.high());
if (destination == kCoreRegisters) {
__ vmov(r2, r3, d7);
__ vmov(r0, r1, d6);
@@ -476,7 +476,7 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
// Handle loading a double from a heap number.
- if (CpuFeatures::IsSupported(VFP3)) {
+ if (CpuFeatures::IsSupported(VFP3) && destination == kVFPRegisters) {
CpuFeatures::Scope scope(VFP3);
// Load the double from tagged HeapNumber to double register.
__ sub(scratch1, object, Operand(kHeapObjectTag));
@@ -492,16 +492,17 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
__ bind(&is_smi);
if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(VFP3);
- // Convert smi to double.
+ // Convert smi to double using VFP instructions.
__ SmiUntag(scratch1, object);
__ vmov(dst.high(), scratch1);
__ vcvt_f64_s32(dst, dst.high());
if (destination == kCoreRegisters) {
+ // Load the converted smi to dst1 and dst2 in double format.
__ vmov(dst1, dst2, dst);
}
} else {
ASSERT(destination == kCoreRegisters);
- // Write Smi to dst1 and dst2 double format.
+ // Write smi to dst1 and dst2 double format.
__ mov(scratch1, Operand(object));
ConvertToDoubleStub stub(dst2, dst1, scratch1, scratch2);
__ push(lr);
@@ -2501,6 +2502,33 @@ void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
// We fall through here if we multiplied a negative number with 0, because
// that would mean we should produce -0.
break;
+ case Token::DIV:
+ // Check for power of two on the right hand side.
+ __ JumpIfNotPowerOfTwoOrZero(right, scratch1, &not_smi_result);
+ // Check for positive and no remainder (scratch1 contains right - 1).
+ __ orr(scratch2, scratch1, Operand(0x80000000u));
+ __ tst(left, scratch2);
+ __ b(ne, &not_smi_result);
+
+ // Perform division by shifting.
+ __ CountLeadingZeros(scratch1, scratch1, scratch2);
+ __ rsb(scratch1, scratch1, Operand(31));
+ __ mov(right, Operand(left, LSR, scratch1));
+ __ Ret();
+ break;
+ case Token::MOD:
+ // Check for two positive smis.
+ __ orr(scratch1, left, Operand(right));
+ __ tst(scratch1, Operand(0x80000000u | kSmiTagMask));
+ __ b(ne, &not_smi_result);
+
+ // Check for power of two on the right hand side.
+ __ JumpIfNotPowerOfTwoOrZero(right, scratch1, &not_smi_result);
+
+ // Perform modulus by masking.
+ __ and_(right, left, Operand(scratch1));
+ __ Ret();
+ break;
default:
UNREACHABLE();
}
@@ -2508,20 +2536,99 @@ void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation(
}
-void TypeRecordingBinaryOpStub::GenerateVFPOperation(
- MacroAssembler* masm) {
- switch (op_) {
- case Token::ADD:
- __ vadd(d5, d6, d7);
- break;
- case Token::SUB:
- __ vsub(d5, d6, d7);
- break;
- case Token::MUL:
- __ vmul(d5, d6, d7);
- break;
- default:
- UNREACHABLE();
+void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
+ bool smi_operands,
+ Label* not_numbers,
+ Label* gc_required) {
+ Register left = r1;
+ Register right = r0;
+ Register scratch1 = r7;
+ Register scratch2 = r9;
+
+ // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending
+ // on whether VFP3 is available.
+ FloatingPointHelper::Destination destination =
+ CpuFeatures::IsSupported(VFP3) && op_ != Token::MOD ?
+ FloatingPointHelper::kVFPRegisters :
+ FloatingPointHelper::kCoreRegisters;
+
+ Register heap_number_map = r6;
+ __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
+ // Allocate new heap number for result.
+ Register result = r5;
+ __ AllocateHeapNumber(
+ result, scratch1, scratch2, heap_number_map, gc_required);
+
+ // Load the operands.
+ if (smi_operands) {
+ if (FLAG_debug_code) {
+ __ AbortIfNotSmi(left);
+ __ AbortIfNotSmi(right);
+ }
+ FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2);
+ } else {
+ FloatingPointHelper::LoadOperands(masm,
+ destination,
+ heap_number_map,
+ scratch1,
+ scratch2,
+ not_numbers);
+ }
+
+ // Calculate the result.
+ if (destination == FloatingPointHelper::kVFPRegisters) {
+ // Using VFP registers:
+ // d6: Left value
+ // d7: Right value
+ CpuFeatures::Scope scope(VFP3);
+ switch (op_) {
+ case Token::ADD:
+ __ vadd(d5, d6, d7);
+ break;
+ case Token::SUB:
+ __ vsub(d5, d6, d7);
+ break;
+ case Token::MUL:
+ __ vmul(d5, d6, d7);
+ break;
+ case Token::DIV:
+ __ vdiv(d5, d6, d7);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ __ sub(r0, result, Operand(kHeapObjectTag));
+ __ vstr(d5, r0, HeapNumber::kValueOffset);
+ __ add(r0, r0, Operand(kHeapObjectTag));
+ __ Ret();
+ } else {
+ // Using core registers:
+ // r0: Left value (least significant part of mantissa).
+ // r1: Left value (sign, exponent, top of mantissa).
+ // r2: Right value (least significant part of mantissa).
+ // r3: Right value (sign, exponent, top of mantissa).
+
+ __ push(lr); // For later.
+ __ PrepareCallCFunction(4, scratch1); // Two doubles are 4 arguments.
+ // Call C routine that may not cause GC or other trouble. r5 is callee
+ // save.
+ __ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
+ // Store answer in the overwritable heap number.
+#if !defined(USE_ARM_EABI)
+ // Double returned in fp coprocessor register 0 and 1, encoded as
+ // register cr8. Offsets must be divisible by 4 for coprocessor so we
+ // need to substract the tag from r5.
+ __ sub(scratch1, result, Operand(kHeapObjectTag));
+ __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset));
+#else
+ // Double returned in registers 0 and 1.
+ __ Strd(r0, r1, FieldMemOperand(result, HeapNumber::kValueOffset));
+#endif
+ __ mov(r0, Operand(result));
+ // And we are done.
+ __ pop(pc);
}
}
@@ -2535,7 +2642,11 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
Label not_smis;
- ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);
+ ASSERT(op_ == Token::ADD ||
+ op_ == Token::SUB ||
+ op_ == Token::MUL ||
+ op_ == Token::DIV ||
+ op_ == Token::MOD);
Register left = r1;
Register right = r0;
@@ -2548,66 +2659,13 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
__ tst(scratch1, Operand(kSmiTagMask));
__ b(ne, &not_smis);
+ // If the smi-smi operation results in a smi return is generated.
GenerateSmiSmiOperation(masm);
// If heap number results are possible generate the result in an allocated
// heap number.
if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) {
- FloatingPointHelper::Destination destination =
- CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ?
- FloatingPointHelper::kVFPRegisters :
- FloatingPointHelper::kCoreRegisters;
-
- Register heap_number_map = r6;
- __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
-
- // Allocate new heap number for result.
- Register heap_number = r5;
- __ AllocateHeapNumber(
- heap_number, scratch1, scratch2, heap_number_map, gc_required);
-
- // Load the smis.
- FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2);
-
- // Calculate the result.
- if (destination == FloatingPointHelper::kVFPRegisters) {
- // Using VFP registers:
- // d6: Left value
- // d7: Right value
- CpuFeatures::Scope scope(VFP3);
- GenerateVFPOperation(masm);
-
- __ sub(r0, heap_number, Operand(kHeapObjectTag));
- __ vstr(d5, r0, HeapNumber::kValueOffset);
- __ add(r0, r0, Operand(kHeapObjectTag));
- __ Ret();
- } else {
- // Using core registers:
- // r0: Left value (least significant part of mantissa).
- // r1: Left value (sign, exponent, top of mantissa).
- // r2: Right value (least significant part of mantissa).
- // r3: Right value (sign, exponent, top of mantissa).
-
- __ push(lr); // For later.
- __ PrepareCallCFunction(4, scratch1); // Two doubles are 4 arguments.
- // Call C routine that may not cause GC or other trouble. r5 is callee
- // save.
- __ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
- // Store answer in the overwritable heap number.
-#if !defined(USE_ARM_EABI)
- // Double returned in fp coprocessor register 0 and 1, encoded as
- // register cr8. Offsets must be divisible by 4 for coprocessor so we
- // need to substract the tag from r5.
- __ sub(scratch1, heap_number, Operand(kHeapObjectTag));
- __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset));
-#else
- // Double returned in registers 0 and 1.
- __ Strd(r0, r1, FieldMemOperand(heap_number, HeapNumber::kValueOffset));
-#endif
- __ mov(r0, Operand(heap_number));
- // And we are done.
- __ pop(pc);
- }
+ GenerateFPOperation(masm, true, NULL, gc_required);
}
__ bind(&not_smis);
}
@@ -2616,7 +2674,11 @@ void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
Label not_smis, call_runtime;
- ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);
+ ASSERT(op_ == Token::ADD ||
+ op_ == Token::SUB ||
+ op_ == Token::MUL ||
+ op_ == Token::DIV ||
+ op_ == Token::MOD);
if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
result_type_ == TRBinaryOpIC::SMI) {
@@ -2648,7 +2710,11 @@ void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
- ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);
+ ASSERT(op_ == Token::ADD ||
+ op_ == Token::SUB ||
+ op_ == Token::MUL ||
+ op_ == Token::DIV ||
+ op_ == Token::MOD);
ASSERT(operands_type_ == TRBinaryOpIC::INT32);
@@ -2657,78 +2723,18 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
- ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);
-
- Register scratch1 = r7;
- Register scratch2 = r9;
+ ASSERT(op_ == Token::ADD ||
+ op_ == Token::SUB ||
+ op_ == Token::MUL ||
+ op_ == Token::DIV ||
+ op_ == Token::MOD);
- Label not_number, call_runtime;
+ Label not_numbers, call_runtime;
ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER);
- Register heap_number_map = r6;
- __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
-
- // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on
- // whether VFP3 is available.
- FloatingPointHelper::Destination destination =
- CpuFeatures::IsSupported(VFP3) ?
- FloatingPointHelper::kVFPRegisters :
- FloatingPointHelper::kCoreRegisters;
- FloatingPointHelper::LoadOperands(masm,
- destination,
- heap_number_map,
- scratch1,
- scratch2,
- &not_number);
- if (destination == FloatingPointHelper::kVFPRegisters) {
- // Use floating point instructions for the binary operation.
- CpuFeatures::Scope scope(VFP3);
- GenerateVFPOperation(masm);
+ GenerateFPOperation(masm, false, &not_numbers, &call_runtime);
- // Get a heap number object for the result - might be left or right if one
- // of these are overwritable.
- GenerateHeapResultAllocation(
- masm, r4, heap_number_map, scratch1, scratch2, &call_runtime);
-
- // Fill the result into the allocated heap number and return.
- __ sub(r0, r4, Operand(kHeapObjectTag));
- __ vstr(d5, r0, HeapNumber::kValueOffset);
- __ add(r0, r0, Operand(kHeapObjectTag));
- __ Ret();
-
- } else {
- // Call a C function for the binary operation.
- // r0/r1: Left operand
- // r2/r3: Right operand
-
- // Get a heap number object for the result - might be left or right if one
- // of these are overwritable. Uses a callee-save register to keep the value
- // across the c call.
- GenerateHeapResultAllocation(
- masm, r4, heap_number_map, scratch1, scratch2, &call_runtime);
-
- __ push(lr); // For returning later (no GC after this point).
- __ PrepareCallCFunction(4, scratch1); // Two doubles count as 4 arguments.
- // Call C routine that may not cause GC or other trouble. r4 is callee
- // saved.
- __ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
-
- // Fill the result into the allocated heap number.
- #if !defined(USE_ARM_EABI)
- // Double returned in fp coprocessor register 0 and 1, encoded as
- // register cr8. Offsets must be divisible by 4 for coprocessor so we
- // need to substract the tag from r5.
- __ sub(scratch1, r4, Operand(kHeapObjectTag));
- __ stc(p1, cr8, MemOperand(scratch1, HeapNumber::kValueOffset));
- #else
- // Double returned in registers 0 and 1.
- __ Strd(r0, r1, FieldMemOperand(r4, HeapNumber::kValueOffset));
- #endif
- __ mov(r0, Operand(r4));
- __ pop(pc); // Return to the pushed lr.
- }
-
- __ bind(&not_number);
+ __ bind(&not_numbers);
GenerateTypeTransition(masm);
__ bind(&call_runtime);
@@ -2737,7 +2743,11 @@ void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
- ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL);
+ ASSERT(op_ == Token::ADD ||
+ op_ == Token::SUB ||
+ op_ == Token::MUL ||
+ op_ == Token::DIV ||
+ op_ == Token::MOD);
Label call_runtime;
@@ -2796,6 +2806,12 @@ void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
case Token::MUL:
__ InvokeBuiltin(Builtins::MUL, JUMP_JS);
break;
+ case Token::DIV:
+ __ InvokeBuiltin(Builtins::DIV, JUMP_JS);
+ break;
+ case Token::MOD:
+ __ InvokeBuiltin(Builtins::MOD, JUMP_JS);
+ break;
default:
UNREACHABLE();
}
diff --git a/deps/v8/src/arm/code-stubs-arm.h b/deps/v8/src/arm/code-stubs-arm.h
index a79b2392d..9e9047e57 100644
--- a/deps/v8/src/arm/code-stubs-arm.h
+++ b/deps/v8/src/arm/code-stubs-arm.h
@@ -289,7 +289,10 @@ class TypeRecordingBinaryOpStub: public CodeStub {
void Generate(MacroAssembler* masm);
void GenerateGeneric(MacroAssembler* masm);
void GenerateSmiSmiOperation(MacroAssembler* masm);
- void GenerateVFPOperation(MacroAssembler* masm);
+ void GenerateFPOperation(MacroAssembler* masm,
+ bool smi_operands,
+ Label* not_numbers,
+ Label* gc_required);
void GenerateSmiCode(MacroAssembler* masm,
Label* gc_required,
SmiCodeGenerateHeapNumberResults heapnumber_results);
diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index 0d429d602..9a6018397 100644
--- a/deps/v8/src/arm/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -4698,12 +4698,15 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
runtime.entry_label(),
AVOID_NANS_AND_INFINITIES);
+ // Convert -0 into +0 by adding +0.
+ __ vmov(d2, 0.0);
+ __ vadd(d0, d2, d0);
// Load 1.0 into d2.
__ vmov(d2, 1.0);
- // Calculate the reciprocal of the square root. 1/sqrt(x) = sqrt(1/x).
- __ vdiv(d0, d2, d0);
+ // Calculate the reciprocal of the square root.
__ vsqrt(d0, d0);
+ __ vdiv(d0, d2, d0);
__ b(&allocate_return);
@@ -4717,6 +4720,9 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
scratch1, scratch2, heap_number_map, s0,
runtime.entry_label(),
AVOID_NANS_AND_INFINITIES);
+ // Convert -0 into +0 by adding +0.
+ __ vmov(d2, 0.0);
+ __ vadd(d0, d2, d0);
__ vsqrt(d0, d0);
__ bind(&allocate_return);
diff --git a/deps/v8/src/arm/deoptimizer-arm.cc b/deps/v8/src/arm/deoptimizer-arm.cc
index 3fd1e394e..75399c69d 100644
--- a/deps/v8/src/arm/deoptimizer-arm.cc
+++ b/deps/v8/src/arm/deoptimizer-arm.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -37,6 +37,14 @@ namespace internal {
int Deoptimizer::table_entry_size_ = 16;
+
+int Deoptimizer::patch_size() {
+ const int kCallInstructionSizeInWords = 3;
+ return kCallInstructionSizeInWords * Assembler::kInstrSize;
+}
+
+
+
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;
@@ -51,6 +59,8 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// For each return after a safepoint insert an absolute call to the
// corresponding deoptimization entry.
+ ASSERT(patch_size() % Assembler::kInstrSize == 0);
+ int call_size_in_words = patch_size() / Assembler::kInstrSize;
unsigned last_pc_offset = 0;
SafepointTable table(function->code());
for (unsigned i = 0; i < table.length(); i++) {
@@ -73,14 +83,13 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
#endif
last_pc_offset = pc_offset;
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- const int kCallInstructionSizeInWords = 3;
- CodePatcher patcher(code->instruction_start() + pc_offset + gap_code_size,
- kCallInstructionSizeInWords);
+ last_pc_offset += gap_code_size;
+ CodePatcher patcher(code->instruction_start() + last_pc_offset,
+ call_size_in_words);
Address deoptimization_entry = Deoptimizer::GetDeoptimizationEntry(
deoptimization_index, Deoptimizer::LAZY);
patcher.masm()->Call(deoptimization_entry, RelocInfo::NONE);
- last_pc_offset +=
- gap_code_size + kCallInstructionSizeInWords * Assembler::kInstrSize;
+ last_pc_offset += patch_size();
}
}
@@ -112,16 +121,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
}
-void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
- Code* check_code,
- Code* replacement_code) {
+void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code) {
UNIMPLEMENTED();
}
-void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
- Code* check_code,
- Code* replacement_code) {
+void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code) {
UNIMPLEMENTED();
}
diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc
index c29886f58..23e5f69eb 100644
--- a/deps/v8/src/arm/full-codegen-arm.cc
+++ b/deps/v8/src/arm/full-codegen-arm.cc
@@ -1550,7 +1550,11 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
OverwriteMode mode) {
__ pop(r1);
- if (op == Token::ADD || op == Token::SUB || op == Token::MUL) {
+ if (op == Token::ADD ||
+ op == Token::SUB ||
+ op == Token::MUL ||
+ op == Token::DIV ||
+ op == Token::MOD) {
TypeRecordingBinaryOpStub stub(op, mode);
__ CallStub(&stub);
} else {
diff --git a/deps/v8/src/arm/jump-target-arm.cc b/deps/v8/src/arm/jump-target-arm.cc
index b9e6ebf24..df370c443 100644
--- a/deps/v8/src/arm/jump-target-arm.cc
+++ b/deps/v8/src/arm/jump-target-arm.cc
@@ -143,6 +143,16 @@ void JumpTarget::DoBind() {
entry_frame_set_ = true;
} else {
cgen()->frame()->MergeTo(&entry_frame_);
+ // On fall through we may have to merge both ways.
+ if (direction_ != FORWARD_ONLY) {
+ // This will not need to adjust the virtual frame entries that are
+ // register allocated since that was done above and they now match.
+ // But it does need to adjust the entry_frame_ of this jump target
+ // to make it potentially less optimistic. Later code can branch back
+ // to this jump target and we need to assert that that code does not
+ // have weaker assumptions about types.
+ entry_frame_.MergeTo(cgen()->frame());
+ }
}
} else {
// If there is no current frame we must have an entry frame which we can
diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc
index c45813838..b7c1b78d1 100644
--- a/deps/v8/src/arm/lithium-arm.cc
+++ b/deps/v8/src/arm/lithium-arm.cc
@@ -655,16 +655,16 @@ LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
LInstruction* instr, int ast_id) {
- ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+ ASSERT(instruction_pending_deoptimization_environment_ == NULL);
ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
- instructions_pending_deoptimization_environment_ = instr;
+ instruction_pending_deoptimization_environment_ = instr;
pending_deoptimization_ast_id_ = ast_id;
return instr;
}
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
- instructions_pending_deoptimization_environment_ = NULL;
+ instruction_pending_deoptimization_environment_ = NULL;
pending_deoptimization_ast_id_ = AstNode::kNoNumber;
}
@@ -1463,6 +1463,13 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+ // The control instruction marking the end of a block that completed
+ // abruptly (e.g., threw an exception). There is nothing specific to do.
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
LOperand* value = UseFixed(instr->value(), r0);
return MarkAsCall(new LThrow(value), instr);
@@ -1837,7 +1844,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
if (pending_deoptimization_ast_id_ == instr->ast_id()) {
LInstruction* result = new LLazyBailout;
result = AssignEnvironment(result);
- instructions_pending_deoptimization_environment_->
+ instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
ClearInstructionPendingDeoptimizationEnvironment();
return result;
diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h
index 3de583298..7f89ee292 100644
--- a/deps/v8/src/arm/lithium-arm.h
+++ b/deps/v8/src/arm/lithium-arm.h
@@ -1855,7 +1855,7 @@ class LChunkBuilder BASE_EMBEDDED {
argument_count_(0),
allocator_(allocator),
position_(RelocInfo::kNoPosition),
- instructions_pending_deoptimization_environment_(NULL),
+ instruction_pending_deoptimization_environment_(NULL),
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
// Build the sequence for the graph.
@@ -1989,7 +1989,7 @@ class LChunkBuilder BASE_EMBEDDED {
int argument_count_;
LAllocator* allocator_;
int position_;
- LInstruction* instructions_pending_deoptimization_environment_;
+ LInstruction* instruction_pending_deoptimization_environment_;
int pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc
index 36498077c..a1adae389 100644
--- a/deps/v8/src/arm/lithium-codegen-arm.cc
+++ b/deps/v8/src/arm/lithium-codegen-arm.cc
@@ -562,17 +562,11 @@ void LCodeGen::AddToTranslation(Translation* translation,
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
- if (instr != NULL) {
- LPointerMap* pointers = instr->pointer_map();
- RecordPosition(pointers->position());
- __ Call(code, mode);
- RegisterLazyDeoptimization(instr);
- } else {
- LPointerMap no_pointers(0);
- RecordPosition(no_pointers.position());
- __ Call(code, mode);
- RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
- }
+ ASSERT(instr != NULL);
+ LPointerMap* pointers = instr->pointer_map();
+ RecordPosition(pointers->position());
+ __ Call(code, mode);
+ RegisterLazyDeoptimization(instr);
}
@@ -585,15 +579,7 @@ void LCodeGen::CallRuntime(Runtime::Function* function,
RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments);
- // Runtime calls to Throw are not supposed to ever return at the
- // call site, so don't register lazy deoptimization for these. We do
- // however have to record a safepoint since throwing exceptions can
- // cause garbage collections.
- if (!instr->IsThrow()) {
- RegisterLazyDeoptimization(instr);
- } else {
- RecordSafepoint(instr->pointer_map(), Safepoint::kNoDeoptimizationIndex);
- }
+ RegisterLazyDeoptimization(instr);
}
@@ -1053,11 +1039,8 @@ void LCodeGen::DoModI(LModI* instr) {
}
// Check for power of two on the right hand side.
- __ sub(scratch, right, Operand(1), SetCC);
- __ b(mi, &call_stub);
- __ tst(scratch, right);
- __ b(ne, &call_stub);
- // Perform modulo operation.
+ __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
+ // Perform modulo operation (scratch contains right - 1).
__ and_(result, scratch, Operand(left));
__ bind(&call_stub);
@@ -2449,12 +2432,17 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ b(ne, &loop);
__ bind(&invoke);
- // Invoke the function. The number of arguments is stored in receiver
- // which is r0, as expected by InvokeFunction.
- v8::internal::ParameterCount actual(receiver);
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
+ pointers,
+ env->deoptimization_index());
+ // The number of arguments is stored in receiver which is r0, as expected
+ // by InvokeFunction.
+ v8::internal::ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}
@@ -3669,10 +3657,14 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
Register object = ToRegister(instr->object());
Register key = ToRegister(instr->key());
__ Push(object, key);
- RecordPosition(instr->pointer_map()->position());
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
+ pointers,
+ env->deoptimization_index());
__ InvokeBuiltin(Builtins::DELETE, CALL_JS, &safepoint_generator);
}
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index 60d0a6b6a..ef351022a 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -1954,6 +1954,17 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
}
+void MacroAssembler::JumpIfNotPowerOfTwoOrZero(
+ Register reg,
+ Register scratch,
+ Label* not_power_of_two_or_zero) {
+ sub(scratch, reg, Operand(1), SetCC);
+ b(mi, not_power_of_two_or_zero);
+ tst(scratch, reg);
+ b(ne, not_power_of_two_or_zero);
+}
+
+
void MacroAssembler::JumpIfNotBothSmi(Register reg1,
Register reg2,
Label* on_not_both_smi) {
@@ -2102,7 +2113,7 @@ void MacroAssembler::CopyFields(Register dst,
void MacroAssembler::CountLeadingZeros(Register zeros, // Answer.
Register source, // Input.
Register scratch) {
- ASSERT(!zeros.is(source) || !source.is(zeros));
+ ASSERT(!zeros.is(source) || !source.is(scratch));
ASSERT(!zeros.is(scratch));
ASSERT(!scratch.is(ip));
ASSERT(!source.is(ip));
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index b6675e47c..a1a13e32e 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -707,6 +707,17 @@ class MacroAssembler: public Assembler {
bool allow_stub_calls() { return allow_stub_calls_; }
// ---------------------------------------------------------------------------
+ // Number utilities
+
+ // Check whether the value of reg is a power of two and not zero. If not
+ // control continues at the label not_power_of_two. If reg is a power of two
+ // the register scratch contains the value of (reg - 1) when control falls
+ // through.
+ void JumpIfNotPowerOfTwoOrZero(Register reg,
+ Register scratch,
+ Label* not_power_of_two_or_zero);
+
+ // ---------------------------------------------------------------------------
// Smi utilities
void SmiTag(Register reg, SBit s = LeaveCC) {
diff --git a/deps/v8/src/arm/virtual-frame-arm.cc b/deps/v8/src/arm/virtual-frame-arm.cc
index 45f48767c..3266a16e3 100644
--- a/deps/v8/src/arm/virtual-frame-arm.cc
+++ b/deps/v8/src/arm/virtual-frame-arm.cc
@@ -68,6 +68,8 @@ void VirtualFrame::PopToR0() {
void VirtualFrame::MergeTo(const VirtualFrame* expected, Condition cond) {
if (Equals(expected)) return;
+ ASSERT((expected->tos_known_smi_map_ & tos_known_smi_map_) ==
+ expected->tos_known_smi_map_);
ASSERT(expected->IsCompatibleWith(this));
MergeTOSTo(expected->top_of_stack_state_, cond);
ASSERT(register_allocation_map_ == expected->register_allocation_map_);
@@ -76,7 +78,7 @@ void VirtualFrame::MergeTo(const VirtualFrame* expected, Condition cond) {
void VirtualFrame::MergeTo(VirtualFrame* expected, Condition cond) {
if (Equals(expected)) return;
- expected->tos_known_smi_map_ &= tos_known_smi_map_;
+ tos_known_smi_map_ &= expected->tos_known_smi_map_;
MergeTOSTo(expected->top_of_stack_state_, cond);
ASSERT(register_allocation_map_ == expected->register_allocation_map_);
}
diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js
index 0d7a7cbc8..a0e3e0bb4 100644
--- a/deps/v8/src/array.js
+++ b/deps/v8/src/array.js
@@ -171,8 +171,9 @@ function Join(array, length, separator, convert) {
}
return %StringBuilderConcat(elements, length2, '');
} finally {
- // Make sure to pop the visited array no matter what happens.
- if (is_array) visited_arrays.pop();
+ // Make sure to remove the last element of the visited array no
+ // matter what happens.
+ if (is_array) visited_arrays.length = visited_arrays.length - 1;
}
}
@@ -603,16 +604,17 @@ function ArraySplice(start, delete_count) {
}
// SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
- // given differently from when an undefined delete count is given.
+ // given as a request to delete all the elements from the start.
+ // And it differs from the case of undefined delete count.
// This does not follow ECMA-262, but we do the same for
// compatibility.
var del_count = 0;
- if (num_arguments > 1) {
+ if (num_arguments == 1) {
+ del_count = len - start_i;
+ } else {
del_count = TO_INTEGER(delete_count);
if (del_count < 0) del_count = 0;
if (del_count > len - start_i) del_count = len - start_i;
- } else {
- del_count = len - start_i;
}
var deleted_elements = [];
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
index fb9a4af14..ca72d6399 100644
--- a/deps/v8/src/assembler.cc
+++ b/deps/v8/src/assembler.cc
@@ -838,8 +838,8 @@ double power_double_double(double x, double y) {
return power_double_int(x, y_int); // Returns 1.0 for exponent 0.
}
if (!isinf(x)) {
- if (y == 0.5) return sqrt(x);
- if (y == -0.5) return 1.0 / sqrt(x);
+ if (y == 0.5) return sqrt(x + 0.0); // -0 must be converted to +0.
+ if (y == -0.5) return 1.0 / sqrt(x + 0.0);
}
if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
return OS::nan_value();
diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc
index 80927a88f..ccfa2b4ec 100644
--- a/deps/v8/src/ast.cc
+++ b/deps/v8/src/ast.cc
@@ -215,17 +215,28 @@ bool IsEqualString(void* first, void* second) {
return (*h1)->Equals(*h2);
}
-bool IsEqualSmi(void* first, void* second) {
- ASSERT((*reinterpret_cast<Smi**>(first))->IsSmi());
- ASSERT((*reinterpret_cast<Smi**>(second))->IsSmi());
- Handle<Smi> h1(reinterpret_cast<Smi**>(first));
- Handle<Smi> h2(reinterpret_cast<Smi**>(second));
- return (*h1)->value() == (*h2)->value();
+
+bool IsEqualNumber(void* first, void* second) {
+ ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
+ ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
+
+ Handle<Object> h1(reinterpret_cast<Object**>(first));
+ Handle<Object> h2(reinterpret_cast<Object**>(second));
+ if (h1->IsSmi()) {
+ return h2->IsSmi() && *h1 == *h2;
+ }
+ if (h2->IsSmi()) return false;
+ Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
+ Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
+ ASSERT(isfinite(n1->value()));
+ ASSERT(isfinite(n2->value()));
+ return n1->value() == n2->value();
}
+
void ObjectLiteral::CalculateEmitStore() {
HashMap properties(&IsEqualString);
- HashMap elements(&IsEqualSmi);
+ HashMap elements(&IsEqualNumber);
for (int i = this->properties()->length() - 1; i >= 0; i--) {
ObjectLiteral::Property* property = this->properties()->at(i);
Literal* literal = property->key();
@@ -238,23 +249,19 @@ void ObjectLiteral::CalculateEmitStore() {
uint32_t hash;
HashMap* table;
void* key;
- uint32_t index;
- Smi* smi_key_location;
if (handle->IsSymbol()) {
Handle<String> name(String::cast(*handle));
- if (name->AsArrayIndex(&index)) {
- smi_key_location = Smi::FromInt(index);
- key = &smi_key_location;
- hash = index;
+ if (name->AsArrayIndex(&hash)) {
+ Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
+ key = key_handle.location();
table = &elements;
} else {
key = name.location();
hash = name->Hash();
table = &properties;
}
- } else if (handle->ToArrayIndex(&index)) {
+ } else if (handle->ToArrayIndex(&hash)) {
key = handle.location();
- hash = index;
table = &elements;
} else {
ASSERT(handle->IsNumber());
diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc
index 16a186fe6..6db9a4819 100644
--- a/deps/v8/src/bootstrapper.cc
+++ b/deps/v8/src/bootstrapper.cc
@@ -1050,7 +1050,6 @@ void Genesis::InstallNativeFunctions() {
INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance",
configure_instance_fun);
- INSTALL_NATIVE(JSFunction, "MakeMessage", make_message_fun);
INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun);
INSTALL_NATIVE(JSObject, "functionCache", function_cache);
}
diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc
index 58dd439d2..d604226d7 100644
--- a/deps/v8/src/builtins.cc
+++ b/deps/v8/src/builtins.cc
@@ -734,35 +734,39 @@ BUILTIN(ArraySplice) {
int n_arguments = args.length() - 1;
- // Return empty array when no arguments are supplied.
- if (n_arguments == 0) {
- return AllocateEmptyJSArray();
- }
-
int relative_start = 0;
- Object* arg1 = args[1];
- if (arg1->IsSmi()) {
- relative_start = Smi::cast(arg1)->value();
- } else if (!arg1->IsUndefined()) {
- return CallJsBuiltin("ArraySplice", args);
+ if (n_arguments > 0) {
+ Object* arg1 = args[1];
+ if (arg1->IsSmi()) {
+ relative_start = Smi::cast(arg1)->value();
+ } else if (!arg1->IsUndefined()) {
+ return CallJsBuiltin("ArraySplice", args);
+ }
}
int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
: Min(relative_start, len);
// SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
- // given differently from when an undefined delete count is given.
+ // given as a request to delete all the elements from the start.
+ // And it differs from the case of undefined delete count.
// This does not follow ECMA-262, but we do the same for
// compatibility.
- int delete_count = len;
- if (n_arguments > 1) {
- Object* arg2 = args[2];
- if (arg2->IsSmi()) {
- delete_count = Smi::cast(arg2)->value();
- } else {
- return CallJsBuiltin("ArraySplice", args);
+ int actual_delete_count;
+ if (n_arguments == 1) {
+ ASSERT(len - actual_start >= 0);
+ actual_delete_count = len - actual_start;
+ } else {
+ int value = 0; // ToInteger(undefined) == 0
+ if (n_arguments > 1) {
+ Object* arg2 = args[2];
+ if (arg2->IsSmi()) {
+ value = Smi::cast(arg2)->value();
+ } else {
+ return CallJsBuiltin("ArraySplice", args);
+ }
}
+ actual_delete_count = Min(Max(value, 0), len - actual_start);
}
- int actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
JSArray* result_array = NULL;
if (actual_delete_count == 0) {
diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc
index a3d200217..f081576aa 100644
--- a/deps/v8/src/deoptimizer.cc
+++ b/deps/v8/src/deoptimizer.cc
@@ -810,6 +810,44 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
}
+void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
+ Code* check_code,
+ Code* replacement_code) {
+ // Iterate over the stack check table and patch every stack check
+ // call to an unconditional call to the replacement code.
+ ASSERT(unoptimized_code->kind() == Code::FUNCTION);
+ Address stack_check_cursor = unoptimized_code->instruction_start() +
+ unoptimized_code->stack_check_table_start();
+ uint32_t table_length = Memory::uint32_at(stack_check_cursor);
+ stack_check_cursor += kIntSize;
+ for (uint32_t i = 0; i < table_length; ++i) {
+ uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset;
+ PatchStackCheckCodeAt(pc_after, check_code, replacement_code);
+ stack_check_cursor += 2 * kIntSize;
+ }
+}
+
+
+void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
+ Code* check_code,
+ Code* replacement_code) {
+ // Iterate over the stack check table and revert the patched
+ // stack check calls.
+ ASSERT(unoptimized_code->kind() == Code::FUNCTION);
+ Address stack_check_cursor = unoptimized_code->instruction_start() +
+ unoptimized_code->stack_check_table_start();
+ uint32_t table_length = Memory::uint32_at(stack_check_cursor);
+ stack_check_cursor += kIntSize;
+ for (uint32_t i = 0; i < table_length; ++i) {
+ uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset;
+ RevertStackCheckCodeAt(pc_after, check_code, replacement_code);
+ stack_check_cursor += 2 * kIntSize;
+ }
+}
+
+
unsigned Deoptimizer::ComputeInputFrameSize() const {
unsigned fixed_size = ComputeFixedSize(function_);
// The fp-to-sp delta already takes the context and the function
diff --git a/deps/v8/src/deoptimizer.h b/deps/v8/src/deoptimizer.h
index 69aa497f8..1d4f4770f 100644
--- a/deps/v8/src/deoptimizer.h
+++ b/deps/v8/src/deoptimizer.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -128,18 +128,33 @@ class Deoptimizer : public Malloced {
static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor* visitor);
+ // The size in bytes of the code required at a lazy deopt patch site.
+ static int patch_size();
+
// Patch all stack guard checks in the unoptimized code to
// unconditionally call replacement_code.
static void PatchStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code);
+ // Patch stack guard check at instruction before pc_after in
+ // the unoptimized code to unconditionally call replacement_code.
+ static void PatchStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code);
+
// Change all patched stack guard checks in the unoptimized code
// back to a normal stack guard check.
static void RevertStackCheckCode(Code* unoptimized_code,
Code* check_code,
Code* replacement_code);
+ // Change all patched stack guard checks in the unoptimized code
+ // back to a normal stack guard check.
+ static void RevertStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code);
+
~Deoptimizer();
void InsertHeapNumberValues(int index, JavaScriptFrame* frame);
diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc
index 2bc878cc4..a3d55921b 100644
--- a/deps/v8/src/factory.cc
+++ b/deps/v8/src/factory.cc
@@ -755,6 +755,24 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
}
+Handle<JSMessageObject> Factory::NewJSMessageObject(
+ Handle<String> type,
+ Handle<JSArray> arguments,
+ int start_position,
+ int end_position,
+ Handle<Object> script,
+ Handle<Object> stack_trace,
+ Handle<Object> stack_frames) {
+ CALL_HEAP_FUNCTION(Heap::AllocateJSMessageObject(*type,
+ *arguments,
+ start_position,
+ end_position,
+ *script,
+ *stack_trace,
+ *stack_frames),
+ JSMessageObject);
+}
+
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
SharedFunctionInfo);
diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h
index a5e159123..ba2b181a3 100644
--- a/deps/v8/src/factory.h
+++ b/deps/v8/src/factory.h
@@ -365,6 +365,15 @@ class Factory : public AllStatic {
Handle<SerializedScopeInfo> scope_info);
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
+ static Handle<JSMessageObject> NewJSMessageObject(
+ Handle<String> type,
+ Handle<JSArray> arguments,
+ int start_position,
+ int end_position,
+ Handle<Object> script,
+ Handle<Object> stack_trace,
+ Handle<Object> stack_frames);
+
static Handle<NumberDictionary> DictionaryAtNumberPut(
Handle<NumberDictionary>,
uint32_t key,
diff --git a/deps/v8/src/gdb-jit.cc b/deps/v8/src/gdb-jit.cc
index b1782cbdd..c26ecf5ea 100644
--- a/deps/v8/src/gdb-jit.cc
+++ b/deps/v8/src/gdb-jit.cc
@@ -201,6 +201,7 @@ class ELFSection : public ZoneObject {
TYPE_SHLIB = 10,
TYPE_DYNSYM = 11,
TYPE_LOPROC = 0x70000000,
+ TYPE_X86_64_UNWIND = 0x70000001,
TYPE_HIPROC = 0x7fffffff,
TYPE_LOUSER = 0x80000000,
TYPE_HIUSER = 0xffffffff
@@ -639,26 +640,53 @@ class ELFSymbolTable : public ELFSection {
class CodeDescription BASE_EMBEDDED {
public:
+
+#ifdef V8_TARGET_ARCH_X64
+ enum StackState {
+ POST_RBP_PUSH,
+ POST_RBP_SET,
+ POST_RBP_POP,
+ STACK_STATE_MAX
+ };
+#endif
+
CodeDescription(const char* name,
Code* code,
Handle<Script> script,
- GDBJITLineInfo* lineinfo)
- : name_(name), code_(code), script_(script), lineinfo_(lineinfo)
- { }
+ GDBJITLineInfo* lineinfo,
+ GDBJITInterface::CodeTag tag)
+ : name_(name),
+ code_(code),
+ script_(script),
+ lineinfo_(lineinfo),
+ tag_(tag) {
+ }
- const char* code_name() const {
+ const char* name() const {
return name_;
}
- uintptr_t code_size() const {
- return code_->instruction_end() - code_->instruction_start();
+ GDBJITLineInfo* lineinfo() const {
+ return lineinfo_;
+ }
+
+ GDBJITInterface::CodeTag tag() const {
+ return tag_;
+ }
+
+ uintptr_t CodeStart() const {
+ return reinterpret_cast<uintptr_t>(code_->instruction_start());
}
- uintptr_t code_start() const {
- return (uintptr_t)code_->instruction_start();
+ uintptr_t CodeEnd() const {
+ return reinterpret_cast<uintptr_t>(code_->instruction_end());
}
- bool is_line_info_available() {
+ uintptr_t CodeSize() const {
+ return CodeEnd() - CodeStart();
+ }
+
+ bool IsLineInfoAvailable() {
return !script_.is_null() &&
script_->source()->IsString() &&
script_->HasValidSource() &&
@@ -666,9 +694,19 @@ class CodeDescription BASE_EMBEDDED {
lineinfo_ != NULL;
}
- GDBJITLineInfo* lineinfo() const { return lineinfo_; }
+#ifdef V8_TARGET_ARCH_X64
+ uintptr_t GetStackStateStartAddress(StackState state) const {
+ ASSERT(state < STACK_STATE_MAX);
+ return stack_state_start_addresses_[state];
+ }
- SmartPointer<char> filename() {
+ void SetStackStateStartAddress(StackState state, uintptr_t addr) {
+ ASSERT(state < STACK_STATE_MAX);
+ stack_state_start_addresses_[state] = addr;
+ }
+#endif
+
+ SmartPointer<char> GetFilename() {
return String::cast(script_->name())->ToCString();
}
@@ -676,11 +714,16 @@ class CodeDescription BASE_EMBEDDED {
return GetScriptLineNumberSafe(script_, pos) + 1;
}
+
private:
const char* name_;
Code* code_;
Handle<Script> script_;
GDBJITLineInfo* lineinfo_;
+ GDBJITInterface::CodeTag tag_;
+#ifdef V8_TARGET_ARCH_X64
+ uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
+#endif
};
@@ -701,9 +744,9 @@ static void CreateSymbolsTable(CodeDescription* desc,
ELFSymbol::TYPE_FILE,
ELFSection::INDEX_ABSOLUTE));
- symtab->Add(ELFSymbol(desc->code_name(),
+ symtab->Add(ELFSymbol(desc->name(),
0,
- desc->code_size(),
+ desc->CodeSize(),
ELFSymbol::BIND_GLOBAL,
ELFSymbol::TYPE_FUNC,
text_section_index));
@@ -723,9 +766,9 @@ class DebugInfoSection : public ELFSection {
w->Write<uint8_t>(sizeof(intptr_t));
w->WriteULEB128(1); // Abbreviation code.
- w->WriteString(*desc_->filename());
- w->Write<intptr_t>(desc_->code_start());
- w->Write<intptr_t>(desc_->code_start() + desc_->code_size());
+ w->WriteString(*desc_->GetFilename());
+ w->Write<intptr_t>(desc_->CodeStart());
+ w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
w->Write<uint32_t>(0);
size.set(static_cast<uint32_t>(w->position() - start));
return true;
@@ -829,7 +872,7 @@ class DebugLineSection : public ELFSection {
w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count.
w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count.
w->Write<uint8_t>(0); // Empty include_directories sequence.
- w->WriteString(*desc_->filename()); // File name.
+ w->WriteString(*desc_->GetFilename()); // File name.
w->WriteULEB128(0); // Current directory.
w->WriteULEB128(0); // Unknown modification time.
w->WriteULEB128(0); // Unknown file size.
@@ -837,7 +880,7 @@ class DebugLineSection : public ELFSection {
prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
- w->Write<intptr_t>(desc_->code_start());
+ w->Write<intptr_t>(desc_->CodeStart());
intptr_t pc = 0;
intptr_t line = 1;
@@ -900,12 +943,238 @@ class DebugLineSection : public ELFSection {
};
+#ifdef V8_TARGET_ARCH_X64
+
+
+class UnwindInfoSection : public ELFSection {
+ public:
+ explicit UnwindInfoSection(CodeDescription *desc);
+ virtual bool WriteBody(Writer *w);
+
+ int WriteCIE(Writer *w);
+ void WriteFDE(Writer *w, int);
+
+ void WriteFDEStateOnEntry(Writer *w);
+ void WriteFDEStateAfterRBPPush(Writer *w);
+ void WriteFDEStateAfterRBPSet(Writer *w);
+ void WriteFDEStateAfterRBPPop(Writer *w);
+
+ void WriteLength(Writer *w,
+ Writer::Slot<uint32_t>* length_slot,
+ int initial_position);
+
+ private:
+ CodeDescription *desc_;
+
+ // DWARF3 Specification, Table 7.23
+ enum CFIInstructions {
+ DW_CFA_ADVANCE_LOC = 0x40,
+ DW_CFA_OFFSET = 0x80,
+ DW_CFA_RESTORE = 0xC0,
+ DW_CFA_NOP = 0x00,
+ DW_CFA_SET_LOC = 0x01,
+ DW_CFA_ADVANCE_LOC1 = 0x02,
+ DW_CFA_ADVANCE_LOC2 = 0x03,
+ DW_CFA_ADVANCE_LOC4 = 0x04,
+ DW_CFA_OFFSET_EXTENDED = 0x05,
+ DW_CFA_RESTORE_EXTENDED = 0x06,
+ DW_CFA_UNDEFINED = 0x07,
+ DW_CFA_SAME_VALUE = 0x08,
+ DW_CFA_REGISTER = 0x09,
+ DW_CFA_REMEMBER_STATE = 0x0A,
+ DW_CFA_RESTORE_STATE = 0x0B,
+ DW_CFA_DEF_CFA = 0x0C,
+ DW_CFA_DEF_CFA_REGISTER = 0x0D,
+ DW_CFA_DEF_CFA_OFFSET = 0x0E,
+
+ DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
+ DW_CFA_EXPRESSION = 0x10,
+ DW_CFA_OFFSET_EXTENDED_SF = 0x11,
+ DW_CFA_DEF_CFA_SF = 0x12,
+ DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
+ DW_CFA_VAL_OFFSET = 0x14,
+ DW_CFA_VAL_OFFSET_SF = 0x15,
+ DW_CFA_VAL_EXPRESSION = 0x16
+ };
+
+ // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
+ enum RegisterMapping {
+ // Only the relevant ones have been added to reduce clutter.
+ AMD64_RBP = 6,
+ AMD64_RSP = 7,
+ AMD64_RA = 16
+ };
+
+ enum CFIConstants {
+ CIE_ID = 0,
+ CIE_VERSION = 1,
+ CODE_ALIGN_FACTOR = 1,
+ DATA_ALIGN_FACTOR = 1,
+ RETURN_ADDRESS_REGISTER = AMD64_RA
+ };
+};
+
+
+void UnwindInfoSection::WriteLength(Writer *w,
+ Writer::Slot<uint32_t>* length_slot,
+ int initial_position) {
+ uint32_t align = (w->position() - initial_position) % kPointerSize;
+
+ if (align != 0) {
+ for (uint32_t i = 0; i < (kPointerSize - align); i++) {
+ w->Write<uint8_t>(DW_CFA_NOP);
+ }
+ }
+
+ ASSERT((w->position() - initial_position) % kPointerSize == 0);
+ length_slot->set(w->position() - initial_position);
+}
+
+
+UnwindInfoSection::UnwindInfoSection(CodeDescription *desc)
+ : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), desc_(desc)
+{ }
+
+int UnwindInfoSection::WriteCIE(Writer *w) {
+ Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
+ uint32_t cie_position = w->position();
+
+ // Write out the CIE header. Currently no 'common instructions' are
+ // emitted onto the CIE; every FDE has its own set of instructions.
+
+ w->Write<uint32_t>(CIE_ID);
+ w->Write<uint8_t>(CIE_VERSION);
+ w->Write<uint8_t>(0); // Null augmentation string.
+ w->WriteSLEB128(CODE_ALIGN_FACTOR);
+ w->WriteSLEB128(DATA_ALIGN_FACTOR);
+ w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
+
+ WriteLength(w, &cie_length_slot, cie_position);
+
+ return cie_position;
+}
+
+
+void UnwindInfoSection::WriteFDE(Writer *w, int cie_position) {
+ // The only FDE for this function. The CFA is the current RBP.
+ Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
+ int fde_position = w->position();
+ w->Write<int32_t>(fde_position - cie_position + 4);
+
+ w->Write<uintptr_t>(desc_->CodeStart());
+ w->Write<uintptr_t>(desc_->CodeSize());
+
+ WriteFDEStateOnEntry(w);
+ WriteFDEStateAfterRBPPush(w);
+ WriteFDEStateAfterRBPSet(w);
+ WriteFDEStateAfterRBPPop(w);
+
+ WriteLength(w, &fde_length_slot, fde_position);
+}
+
+
+void UnwindInfoSection::WriteFDEStateOnEntry(Writer *w) {
+ // The first state, just after the control has been transferred to the the
+ // function.
+
+ // RBP for this function will be the value of RSP after pushing the RBP
+ // for the previous function. The previous RBP has not been pushed yet.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
+ w->WriteULEB128(AMD64_RSP);
+ w->WriteSLEB128(-kPointerSize);
+
+ // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
+ // and hence omitted from the next states.
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RA);
+ w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
+
+ // The RBP of the previous function is still in RBP.
+ w->Write<uint8_t>(DW_CFA_SAME_VALUE);
+ w->WriteULEB128(AMD64_RBP);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>(
+ desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
+}
+
+
+void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer *w) {
+ // The second state, just after RBP has been pushed.
+
+ // RBP / CFA for this function is now the current RSP, so just set the
+ // offset from the previous rule (from -8) to 0.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
+ w->WriteULEB128(0);
+
+ // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
+ // in this and the next state, and hence omitted in the next state.
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>(
+ desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
+}
+
+
+void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer *w) {
+ // The third state, after the RBP has been set.
+
+ // The CFA can now directly be set to RBP.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteULEB128(0);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>(
+ desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
+}
+
+
+void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer *w) {
+ // The fourth (final) state. The RBP has been popped (just before issuing a
+ // return).
+
+ // The CFA can is now calculated in the same way as in the first state.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
+ w->WriteULEB128(AMD64_RSP);
+ w->WriteSLEB128(-kPointerSize);
+
+ // The RBP
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>(desc_->CodeEnd());
+}
+
+
+bool UnwindInfoSection::WriteBody(Writer *w) {
+ uint32_t cie_position = WriteCIE(w);
+ WriteFDE(w, cie_position);
+ return true;
+}
+
+
+#endif // V8_TARGET_ARCH_X64
+
+
static void CreateDWARFSections(CodeDescription* desc, ELF* elf) {
- if (desc->is_line_info_available()) {
+ if (desc->IsLineInfoAvailable()) {
elf->AddSection(new DebugInfoSection(desc));
elf->AddSection(new DebugAbbrevSection);
elf->AddSection(new DebugLineSection(desc));
}
+#ifdef V8_TARGET_ARCH_X64
+ elf->AddSection(new UnwindInfoSection(desc));
+#endif
}
@@ -1005,9 +1274,9 @@ static JITCodeEntry* CreateELFObject(CodeDescription* desc) {
new FullHeaderELFSection(".text",
ELFSection::TYPE_NOBITS,
kCodeAlignment,
- desc->code_start(),
+ desc->CodeStart(),
0,
- desc->code_size(),
+ desc->CodeSize(),
ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
CreateSymbolsTable(desc, &elf, text_section_index);
@@ -1065,15 +1334,66 @@ void GDBJITInterface::AddCode(Handle<String> name,
if (!name.is_null()) {
SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS);
- AddCode(*name_cstring, *code, *script);
+ AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script);
+ } else {
+ AddCode("", *code, GDBJITInterface::FUNCTION, *script);
+ }
+}
+
+static void AddUnwindInfo(CodeDescription *desc) {
+#ifdef V8_TARGET_ARCH_X64
+ if (desc->tag() == GDBJITInterface::FUNCTION) {
+ // To avoid propagating unwinding information through
+ // compilation pipeline we rely on function prologue
+ // and epilogue being the same for all code objects generated
+ // by the full code generator.
+ static const int kFramePointerPushOffset = 1;
+ static const int kFramePointerSetOffset = 4;
+ static const int kFramePointerPopOffset = -3;
+
+ uintptr_t frame_pointer_push_address =
+ desc->CodeStart() + kFramePointerPushOffset;
+
+ uintptr_t frame_pointer_set_address =
+ desc->CodeStart() + kFramePointerSetOffset;
+
+ uintptr_t frame_pointer_pop_address =
+ desc->CodeEnd() + kFramePointerPopOffset;
+
+#ifdef DEBUG
+ static const uint8_t kFramePointerPushInstruction = 0x48; // push ebp
+ static const uint16_t kFramePointerSetInstruction = 0x5756; // mov ebp, esp
+ static const uint8_t kFramePointerPopInstruction = 0xBE; // pop ebp
+
+ ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_push_address) ==
+ kFramePointerPushInstruction);
+ ASSERT(*reinterpret_cast<uint16_t*>(frame_pointer_set_address) ==
+ kFramePointerSetInstruction);
+ ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_pop_address) ==
+ kFramePointerPopInstruction);
+#endif
+
+ desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
+ frame_pointer_push_address);
+ desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
+ frame_pointer_set_address);
+ desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
+ frame_pointer_pop_address);
} else {
- AddCode("", *code, *script);
+ desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
+ desc->CodeStart());
+ desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
+ desc->CodeStart());
+ desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
+ desc->CodeEnd());
}
+#endif // V8_TARGET_ARCH_X64
}
void GDBJITInterface::AddCode(const char* name,
Code* code,
+ GDBJITInterface::CodeTag tag,
Script* script) {
if (!FLAG_gdbjit) return;
AssertNoAllocation no_gc;
@@ -1086,14 +1406,16 @@ void GDBJITInterface::AddCode(const char* name,
code,
script != NULL ? Handle<Script>(script)
: Handle<Script>(),
- lineinfo);
+ lineinfo,
+ tag);
- if (!FLAG_gdbjit_full && !code_desc.is_line_info_available()) {
+ if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
delete lineinfo;
entries.Remove(code, HashForCodeObject(code));
return;
}
+ AddUnwindInfo(&code_desc);
JITCodeEntry* entry = CreateELFObject(&code_desc);
ASSERT(!IsLineInfoTagged(entry));
@@ -1120,7 +1442,7 @@ void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
builder.AddFormatted(": code object %p", static_cast<void*>(code));
}
- AddCode(builder.Finalize(), code);
+ AddCode(builder.Finalize(), code, tag);
}
diff --git a/deps/v8/src/gdb-jit.h b/deps/v8/src/gdb-jit.h
index 5d348b69a..d46fec63a 100644
--- a/deps/v8/src/gdb-jit.h
+++ b/deps/v8/src/gdb-jit.h
@@ -55,7 +55,8 @@ namespace internal {
V(STUB) \
V(BUILTIN) \
V(SCRIPT) \
- V(EVAL)
+ V(EVAL) \
+ V(FUNCTION)
class GDBJITLineInfo : public Malloced {
public:
@@ -109,6 +110,7 @@ class GDBJITInterface: public AllStatic {
static void AddCode(const char* name,
Code* code,
+ CodeTag tag,
Script* script = NULL);
static void AddCode(Handle<String> name,
diff --git a/deps/v8/src/hashmap.h b/deps/v8/src/hashmap.h
index 3b947beb5..27989889c 100644
--- a/deps/v8/src/hashmap.h
+++ b/deps/v8/src/hashmap.h
@@ -49,7 +49,8 @@ class HashMap {
typedef bool (*MatchFun) (void* key1, void* key2);
// Dummy constructor. This constructor doesn't set up the hash
- // map properly so don't use it unless you have good reason.
+ // map properly so don't use it unless you have good reason (e.g.,
+ // you know that the HashMap will never be used).
HashMap();
// initial_capacity is the size of the initial hash map;
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index 7c7f3d269..0093829b1 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -1826,6 +1826,12 @@ bool Heap::CreateInitialMaps() {
}
set_shared_function_info_map(Map::cast(obj));
+ { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
+ JSMessageObject::kSize);
+ if (!maybe_obj->ToObject(&obj)) return false;
+ }
+ set_message_object_map(Map::cast(obj));
+
ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
return true;
}
@@ -2329,6 +2335,32 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
}
+MaybeObject* Heap::AllocateJSMessageObject(String* type,
+ JSArray* arguments,
+ int start_position,
+ int end_position,
+ Object* script,
+ Object* stack_trace,
+ Object* stack_frames) {
+ Object* result;
+ { MaybeObject* maybe_result = Allocate(message_object_map(), NEW_SPACE);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ JSMessageObject* message = JSMessageObject::cast(result);
+ message->set_properties(Heap::empty_fixed_array());
+ message->set_elements(Heap::empty_fixed_array());
+ message->set_type(type);
+ message->set_arguments(arguments);
+ message->set_start_position(start_position);
+ message->set_end_position(end_position);
+ message->set_script(script);
+ message->set_stack_trace(stack_trace);
+ message->set_stack_frames(stack_frames);
+ return result;
+}
+
+
+
// Returns true for a character in a range. Both limits are inclusive.
static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
// This makes uses of the the unsigned wraparound.
diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h
index 1c86817aa..e051b5023 100644
--- a/deps/v8/src/heap.h
+++ b/deps/v8/src/heap.h
@@ -94,6 +94,7 @@ namespace internal {
V(Map, oddball_map, OddballMap) \
V(Map, global_property_cell_map, GlobalPropertyCellMap) \
V(Map, shared_function_info_map, SharedFunctionInfoMap) \
+ V(Map, message_object_map, JSMessageObjectMap) \
V(Map, proxy_map, ProxyMap) \
V(Object, nan_value, NanValue) \
V(Object, minus_zero_value, MinusZeroValue) \
@@ -628,6 +629,19 @@ class Heap : public AllStatic {
// Please note this does not perform a garbage collection.
MUST_USE_RESULT static MaybeObject* AllocateSharedFunctionInfo(Object* name);
+ // Allocates a new JSMessageObject object.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+ // failed.
+ // Please note that this does not perform a garbage collection.
+ MUST_USE_RESULT static MaybeObject* AllocateJSMessageObject(
+ String* type,
+ JSArray* arguments,
+ int start_position,
+ int end_position,
+ Object* script,
+ Object* stack_trace,
+ Object* stack_frames);
+
// Allocates a new cons string object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc
index 2f8b6e263..c24ddfc80 100644
--- a/deps/v8/src/hydrogen-instructions.cc
+++ b/deps/v8/src/hydrogen-instructions.cc
@@ -253,6 +253,7 @@ bool HValue::Equals(HValue* other) const {
if (other->opcode() != opcode()) return false;
if (!other->representation().Equals(representation())) return false;
if (!other->type_.Equals(type_)) return false;
+ if (other->flags() != flags()) return false;
if (OperandCount() != other->OperandCount()) return false;
for (int i = 0; i < OperandCount(); ++i) {
if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h
index ff8170012..eaab8adef 100644
--- a/deps/v8/src/hydrogen-instructions.h
+++ b/deps/v8/src/hydrogen-instructions.h
@@ -64,6 +64,7 @@ class LChunkBuilder;
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
+ V(AbnormalExit) \
V(AccessArgumentsAt) \
V(Add) \
V(ApplyArguments) \
@@ -834,12 +835,11 @@ class HReturn: public HUnaryControlInstruction {
};
-class HThrow: public HUnaryControlInstruction {
+class HAbnormalExit: public HControlInstruction {
public:
- explicit HThrow(HValue* value)
- : HUnaryControlInstruction(value, NULL, NULL) { }
+ HAbnormalExit() : HControlInstruction(NULL, NULL) { }
- DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+ DECLARE_CONCRETE_INSTRUCTION(AbnormalExit, "abnormal_exit")
};
@@ -866,6 +866,20 @@ class HUnaryOperation: public HInstruction {
};
+class HThrow: public HUnaryOperation {
+ public:
+ explicit HThrow(HValue* value) : HUnaryOperation(value) {
+ SetAllSideEffects();
+ }
+
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
+};
+
+
class HChange: public HUnaryOperation {
public:
HChange(HValue* value,
@@ -989,7 +1003,7 @@ class HStackCheck: public HInstruction {
public:
HStackCheck() { }
- DECLARE_CONCRETE_INSTRUCTION(Throw, "stack_check")
+ DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack_check")
};
@@ -1831,6 +1845,7 @@ class HApplyArguments: public HInstruction {
SetOperandAt(1, receiver);
SetOperandAt(2, length);
SetOperandAt(3, elements);
+ SetAllSideEffects();
}
virtual Representation RequiredInputRepresentation(int index) const {
@@ -1850,8 +1865,6 @@ class HApplyArguments: public HInstruction {
DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply_arguments")
-
-
protected:
virtual void InternalSetOperandAt(int index, HValue* value) {
operands_[index] = value;
@@ -3073,6 +3086,10 @@ class HTypeof: public HUnaryOperation {
set_representation(Representation::Tagged());
}
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+
DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
};
diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc
index 84623069a..9d5aa2be3 100644
--- a/deps/v8/src/hydrogen.cc
+++ b/deps/v8/src/hydrogen.cc
@@ -1813,15 +1813,6 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
HValue* use,
Representation to,
bool is_truncating) {
- // Propagate flags for negative zero checks upwards from conversions
- // int32-to-tagged and int32-to-double.
- Representation from = value->representation();
- if (from.IsInteger32()) {
- ASSERT(to.IsTagged() || to.IsDouble());
- BitVector visited(GetMaximumValueID());
- PropagateMinusZeroChecks(value, &visited);
- }
-
// Insert the representation change right before its use. For phi-uses we
// insert at the end of the corresponding predecessor.
HBasicBlock* insert_block = use->block();
@@ -1984,6 +1975,30 @@ void HGraph::InsertRepresentationChanges() {
}
+void HGraph::ComputeMinusZeroChecks() {
+ BitVector visited(GetMaximumValueID());
+ for (int i = 0; i < blocks_.length(); ++i) {
+ for (HInstruction* current = blocks_[i]->first();
+ current != NULL;
+ current = current->next()) {
+ if (current->IsChange()) {
+ HChange* change = HChange::cast(current);
+ // Propagate flags for negative zero checks upwards from conversions
+ // int32-to-tagged and int32-to-double.
+ Representation from = change->value()->representation();
+ ASSERT(from.Equals(change->from()));
+ if (from.IsInteger32()) {
+ ASSERT(change->to().IsTagged() || change->to().IsDouble());
+ ASSERT(visited.IsEmpty());
+ PropagateMinusZeroChecks(change->value(), &visited);
+ visited.Clear();
+ }
+ }
+ }
+ }
+}
+
+
// Implementation of utility classes to represent an expression's context in
// the AST.
AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
@@ -2243,6 +2258,7 @@ HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
graph_->InitializeInferredTypes();
graph_->Canonicalize();
graph_->InsertRepresentationChanges();
+ graph_->ComputeMinusZeroChecks();
// Eliminate redundant stack checks on backwards branches.
HStackCheckEliminator sce(graph_);
@@ -3540,9 +3556,11 @@ void HGraphBuilder::VisitThrow(Throw* expr) {
VISIT_FOR_VALUE(expr->exception());
HValue* value = environment()->Pop();
- HControlInstruction* instr = new HThrow(value);
+ HThrow* instr = new HThrow(value);
instr->set_position(expr->position());
- current_subgraph_->FinishExit(instr);
+ AddInstruction(instr);
+ AddSimulate(expr->id());
+ current_subgraph_->FinishExit(new HAbnormalExit);
}
diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h
index dbcb82e6e..952c04fde 100644
--- a/deps/v8/src/hydrogen.h
+++ b/deps/v8/src/hydrogen.h
@@ -307,6 +307,7 @@ class HGraph: public HSubgraph {
void InitializeInferredTypes();
void InsertTypeConversions();
void InsertRepresentationChanges();
+ void ComputeMinusZeroChecks();
bool ProcessArgumentsObject();
void EliminateRedundantPhis();
void Canonicalize();
diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc
index 006ee46ed..a9c3085ba 100644
--- a/deps/v8/src/ia32/code-stubs-ia32.cc
+++ b/deps/v8/src/ia32/code-stubs-ia32.cc
@@ -3499,10 +3499,12 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ j(not_equal, &not_minus_half);
// Calculates reciprocal of square root.
- // Note that 1/sqrt(x) = sqrt(1/x))
- __ divsd(xmm3, xmm0);
- __ movsd(xmm1, xmm3);
+ // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
+ __ xorpd(xmm1, xmm1);
+ __ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
+ __ divsd(xmm3, xmm1);
+ __ movsd(xmm1, xmm3);
__ jmp(&allocate_return);
// Test for 0.5.
@@ -3514,7 +3516,9 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ ucomisd(xmm2, xmm1);
__ j(not_equal, &call_runtime);
// Calculates square root.
- __ movsd(xmm1, xmm0);
+ // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
+ __ xorpd(xmm1, xmm1);
+ __ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
__ bind(&allocate_return);
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index 2b48b0bc9..73c952a35 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -7951,10 +7951,12 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ j(not_equal, &not_minus_half);
// Calculates reciprocal of square root.
- // Note that 1/sqrt(x) = sqrt(1/x))
- __ divsd(xmm3, xmm0);
- __ movsd(xmm1, xmm3);
+ // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
+ __ xorpd(xmm1, xmm1);
+ __ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
+ __ divsd(xmm3, xmm1);
+ __ movsd(xmm1, xmm3);
__ jmp(&allocate_return);
// Test for 0.5.
@@ -7966,7 +7968,9 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ ucomisd(xmm2, xmm1);
call_runtime.Branch(not_equal);
// Calculates square root.
- __ movsd(xmm1, xmm0);
+ // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
+ __ xorpd(xmm1, xmm1);
+ __ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
JumpTarget done;
diff --git a/deps/v8/src/ia32/deoptimizer-ia32.cc b/deps/v8/src/ia32/deoptimizer-ia32.cc
index e9e3fcfb7..35c671365 100644
--- a/deps/v8/src/ia32/deoptimizer-ia32.cc
+++ b/deps/v8/src/ia32/deoptimizer-ia32.cc
@@ -37,9 +37,14 @@
namespace v8 {
namespace internal {
-
int Deoptimizer::table_entry_size_ = 10;
+
+int Deoptimizer::patch_size() {
+ return Assembler::kCallInstructionLength;
+}
+
+
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;
@@ -48,14 +53,19 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// Get the optimized code.
Code* code = function->code();
- // Invalidate the relocation information, as it will become invalid by the
- // code patching below, and is not needed any more.
- code->InvalidateRelocation();
-
// For each return after a safepoint insert a absolute call to the
// corresponding deoptimization entry.
unsigned last_pc_offset = 0;
SafepointTable table(function->code());
+
+ // We will overwrite the code's relocation info in-place. Relocation info
+ // is written backward. The relocation info is the payload of a byte array.
+ // Later on we will align this at the start of the byte array and create
+ // a trash byte array of the remaining space.
+ ByteArray* reloc_info = code->relocation_info();
+ Address end_address = reloc_info->address() + reloc_info->Size();
+ RelocInfoWriter reloc_info_writer(end_address, code->instruction_start());
+
for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(i);
SafepointEntry safepoint_entry = table.GetEntry(i);
@@ -72,12 +82,15 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
#endif
last_pc_offset = pc_offset;
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- CodePatcher patcher(
- code->instruction_start() + pc_offset + gap_code_size,
- Assembler::kCallInstructionLength);
- patcher.masm()->call(GetDeoptimizationEntry(deoptimization_index, LAZY),
- RelocInfo::NONE);
- last_pc_offset += gap_code_size + Assembler::kCallInstructionLength;
+ last_pc_offset += gap_code_size;
+ Address call_pc = code->instruction_start() + last_pc_offset;
+ CodePatcher patcher(call_pc, patch_size());
+ Address entry = GetDeoptimizationEntry(deoptimization_index, LAZY);
+ patcher.masm()->call(entry, RelocInfo::NONE);
+ last_pc_offset += patch_size();
+ RelocInfo rinfo(call_pc + 1, RelocInfo::RUNTIME_ENTRY,
+ reinterpret_cast<intptr_t>(entry));
+ reloc_info_writer.Write(&rinfo);
}
}
#ifdef DEBUG
@@ -90,6 +103,40 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
}
#endif
+ // Move the relocation info to the beginning of the byte array.
+ int reloc_size = end_address - reloc_info_writer.pos();
+ memmove(code->relocation_start(), reloc_info_writer.pos(), reloc_size);
+
+ // The relocation info is in place, update the size.
+ reloc_info->set_length(reloc_size);
+
+ // Handle the junk part after the new relocation info. We will create
+ // a non-live object in the extra space at the end of the former reloc info.
+ Address junk = reloc_info->address() + reloc_info->Size();
+ ASSERT(junk <= end_address);
+
+ if (end_address - junk <= ByteArray::kHeaderSize) {
+ // We get in here if there is not enough space for a ByteArray.
+
+ // Both addresses are kPointerSize alligned.
+ CHECK_EQ((end_address - junk) % 4, 0);
+ Map* filler_map = Heap::one_pointer_filler_map();
+ while (junk < end_address) {
+ HeapObject::FromAddress(junk)->set_map(filler_map);
+ junk += kPointerSize;
+ }
+ } else {
+ int size = end_address - junk;
+ // Since the reloc_end address and junk are both alligned, we shouild,
+ // never have junk which is not a multipla of kPointerSize.
+ CHECK_EQ(size % kPointerSize, 0);
+ CHECK_GT(size, 0);
+ HeapObject* junk_object = HeapObject::FromAddress(junk);
+ junk_object->set_map(Heap::byte_array_map());
+ int length = ByteArray::LengthFor(end_address - junk);
+ ByteArray::cast(junk_object)->set_length(length);
+ }
+
// Add the deoptimizing code to the list.
DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
node->set_next(deoptimizing_code_list_);
@@ -106,71 +153,53 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
}
-void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
- Code* check_code,
- Code* replacement_code) {
- // Iterate the unoptimized code and patch every stack check except at
- // the function entry. This code assumes the function entry stack
- // check appears first i.e., is not deferred or otherwise reordered.
- ASSERT(unoptimized_code->kind() == Code::FUNCTION);
- bool first = true;
- for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
- !it.done();
- it.next()) {
- RelocInfo* rinfo = it.rinfo();
- if (rinfo->target_address() == Code::cast(check_code)->entry()) {
- if (first) {
- first = false;
- } else {
- // The stack check code matches the pattern:
- //
- // cmp esp, <limit>
- // jae ok
- // call <stack guard>
- // test eax, <loop nesting depth>
- // ok: ...
- //
- // We will patch away the branch so the code is:
- //
- // cmp esp, <limit> ;; Not changed
- // nop
- // nop
- // call <on-stack replacment>
- // test eax, <loop nesting depth>
- // ok:
- Address call_target_address = rinfo->pc();
- ASSERT(*(call_target_address - 3) == 0x73 && // jae
- *(call_target_address - 2) == 0x07 && // offset
- *(call_target_address - 1) == 0xe8); // call
- *(call_target_address - 3) = 0x90; // nop
- *(call_target_address - 2) = 0x90; // nop
- rinfo->set_target_address(replacement_code->entry());
- }
- }
- }
+void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code) {
+ Address call_target_address = pc_after - kPointerSize;
+ ASSERT(check_code->entry() ==
+ Assembler::target_address_at(call_target_address));
+ // The stack check code matches the pattern:
+ //
+ // cmp esp, <limit>
+ // jae ok
+ // call <stack guard>
+ // test eax, <loop nesting depth>
+ // ok: ...
+ //
+ // We will patch away the branch so the code is:
+ //
+ // cmp esp, <limit> ;; Not changed
+ // nop
+ // nop
+ // call <on-stack replacment>
+ // test eax, <loop nesting depth>
+ // ok:
+ ASSERT(*(call_target_address - 3) == 0x73 && // jae
+ *(call_target_address - 2) == 0x07 && // offset
+ *(call_target_address - 1) == 0xe8); // call
+ *(call_target_address - 3) = 0x90; // nop
+ *(call_target_address - 2) = 0x90; // nop
+ Assembler::set_target_address_at(call_target_address,
+ replacement_code->entry());
}
-void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
- Code* check_code,
- Code* replacement_code) {
- // Iterate the unoptimized code and revert all the patched stack checks.
- for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
- !it.done();
- it.next()) {
- RelocInfo* rinfo = it.rinfo();
- if (rinfo->target_address() == replacement_code->entry()) {
- // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
- // restore the conditional branch.
- Address call_target_address = rinfo->pc();
- ASSERT(*(call_target_address - 3) == 0x90 && // nop
- *(call_target_address - 2) == 0x90 && // nop
- *(call_target_address - 1) == 0xe8); // call
- *(call_target_address - 3) = 0x73; // jae
- *(call_target_address - 2) = 0x07; // offset
- rinfo->set_target_address(check_code->entry());
- }
- }
+void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code) {
+ Address call_target_address = pc_after - kPointerSize;
+ ASSERT(replacement_code->entry() ==
+ Assembler::target_address_at(call_target_address));
+ // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
+ // restore the conditional branch.
+ ASSERT(*(call_target_address - 3) == 0x90 && // nop
+ *(call_target_address - 2) == 0x90 && // nop
+ *(call_target_address - 1) == 0xe8); // call
+ *(call_target_address - 3) = 0x73; // jae
+ *(call_target_address - 2) = 0x07; // offset
+ Assembler::set_target_address_at(call_target_address,
+ check_code->entry());
}
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc
index d35bfc9a2..ae8fe8d65 100644
--- a/deps/v8/src/ia32/lithium-codegen-ia32.cc
+++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc
@@ -37,6 +37,8 @@ namespace v8 {
namespace internal {
+// When invoking builtins, we need to record the safepoint in the middle of
+// the invoke instruction sequence generated by the macro assembler.
class SafepointGenerator : public PostCallGenerator {
public:
SafepointGenerator(LCodeGen* codegen,
@@ -366,17 +368,11 @@ void LCodeGen::AddToTranslation(Translation* translation,
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
- if (instr != NULL) {
- LPointerMap* pointers = instr->pointer_map();
- RecordPosition(pointers->position());
- __ call(code, mode);
- RegisterLazyDeoptimization(instr);
- } else {
- LPointerMap no_pointers(0);
- RecordPosition(no_pointers.position());
- __ call(code, mode);
- RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
- }
+ ASSERT(instr != NULL);
+ LPointerMap* pointers = instr->pointer_map();
+ RecordPosition(pointers->position());
+ __ call(code, mode);
+ RegisterLazyDeoptimization(instr);
// Signal that we don't inline smi code before these stubs in the
// optimizing code generator.
@@ -391,22 +387,12 @@ void LCodeGen::CallRuntime(Runtime::Function* function,
int num_arguments,
LInstruction* instr) {
ASSERT(instr != NULL);
+ ASSERT(instr->HasPointerMap());
LPointerMap* pointers = instr->pointer_map();
- ASSERT(pointers != NULL);
RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments);
- // Runtime calls to Throw are not supposed to ever return at the
- // call site, so don't register lazy deoptimization for these. We do
- // however have to record a safepoint since throwing exceptions can
- // cause garbage collections.
- // BUG(3243555): register a lazy deoptimization point at throw. We need
- // it to be able to inline functions containing a throw statement.
- if (!instr->IsThrow()) {
- RegisterLazyDeoptimization(instr);
- } else {
- RecordSafepoint(instr->pointer_map(), Safepoint::kNoDeoptimizationIndex);
- }
+ RegisterLazyDeoptimization(instr);
}
@@ -2145,11 +2131,16 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// Invoke the function.
__ bind(&invoke);
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
+ SafepointGenerator safepoint_generator(this,
+ pointers,
+ env->deoptimization_index());
ASSERT(receiver.is(eax));
v8::internal::ParameterCount actual(eax);
- SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
__ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator);
}
@@ -2397,6 +2388,8 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
__ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity));
__ ucomisd(xmm_scratch, input_reg);
DeoptimizeIf(equal, instr->environment());
+ __ xorpd(xmm_scratch, xmm_scratch);
+ __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
__ sqrtsd(input_reg, input_reg);
}
@@ -3575,10 +3568,14 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
} else {
__ push(ToOperand(key));
}
- RecordPosition(instr->pointer_map()->position());
+ ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
+ LPointerMap* pointers = instr->pointer_map();
+ LEnvironment* env = instr->deoptimization_environment();
+ RecordPosition(pointers->position());
+ RegisterEnvironmentForDeoptimization(env);
SafepointGenerator safepoint_generator(this,
- instr->pointer_map(),
- Safepoint::kNoDeoptimizationIndex);
+ pointers,
+ env->deoptimization_index());
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
}
diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc
index 100a2d44f..207036732 100644
--- a/deps/v8/src/ia32/lithium-ia32.cc
+++ b/deps/v8/src/ia32/lithium-ia32.cc
@@ -658,16 +658,16 @@ LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
LInstruction* instr, int ast_id) {
- ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+ ASSERT(instruction_pending_deoptimization_environment_ == NULL);
ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
- instructions_pending_deoptimization_environment_ = instr;
+ instruction_pending_deoptimization_environment_ = instr;
pending_deoptimization_ast_id_ = ast_id;
return instr;
}
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
- instructions_pending_deoptimization_environment_ = NULL;
+ instruction_pending_deoptimization_environment_ = NULL;
pending_deoptimization_ast_id_ = AstNode::kNoNumber;
}
@@ -1507,6 +1507,13 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+ // The control instruction marking the end of a block that completed
+ // abruptly (e.g., threw an exception). There is nothing specific to do.
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
LOperand* value = UseFixed(instr->value(), eax);
return MarkAsCall(new LThrow(value), instr);
@@ -1875,10 +1882,11 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
// If there is an instruction pending deoptimization environment create a
// lazy bailout instruction to capture the environment.
- if (pending_deoptimization_ast_id_ == instr->ast_id()) {
+ if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
+ ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
LLazyBailout* lazy_bailout = new LLazyBailout;
LInstruction* result = AssignEnvironment(lazy_bailout);
- instructions_pending_deoptimization_environment_->
+ instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
ClearInstructionPendingDeoptimizationEnvironment();
return result;
diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h
index 1cdd31ede..1adc13e4d 100644
--- a/deps/v8/src/ia32/lithium-ia32.h
+++ b/deps/v8/src/ia32/lithium-ia32.h
@@ -1881,7 +1881,7 @@ class LChunkBuilder BASE_EMBEDDED {
argument_count_(0),
allocator_(allocator),
position_(RelocInfo::kNoPosition),
- instructions_pending_deoptimization_environment_(NULL),
+ instruction_pending_deoptimization_environment_(NULL),
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
// Build the sequence for the graph.
@@ -2015,7 +2015,7 @@ class LChunkBuilder BASE_EMBEDDED {
int argument_count_;
LAllocator* allocator_;
int position_;
- LInstruction* instructions_pending_deoptimization_environment_;
+ LInstruction* instruction_pending_deoptimization_environment_;
int pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
diff --git a/deps/v8/src/lithium-allocator.cc b/deps/v8/src/lithium-allocator.cc
index cac7d65e9..81877f376 100644
--- a/deps/v8/src/lithium-allocator.cc
+++ b/deps/v8/src/lithium-allocator.cc
@@ -1068,9 +1068,7 @@ void LAllocator::ResolveControlFlow(LiveRange* range,
HBasicBlock* block,
HBasicBlock* pred) {
LifetimePosition pred_end =
- LifetimePosition::FromInstructionIndex(pred->last_instruction_index()).
- PrevInstruction();
-
+ LifetimePosition::FromInstructionIndex(pred->last_instruction_index());
LifetimePosition cur_start =
LifetimePosition::FromInstructionIndex(block->first_instruction_index());
LiveRange* pred_cover = NULL;
@@ -1245,7 +1243,7 @@ void LAllocator::BuildLiveRanges() {
LifetimePosition start = LifetimePosition::FromInstructionIndex(
block->first_instruction_index());
LifetimePosition end = LifetimePosition::FromInstructionIndex(
- back_edge->last_instruction_index());
+ back_edge->last_instruction_index()).NextInstruction();
while (!iterator.Done()) {
int operand_index = iterator.Current();
LiveRange* range = LiveRangeFor(operand_index);
@@ -2019,6 +2017,11 @@ LiveRange* LAllocator::SplitAt(LiveRange* range, LifetimePosition pos) {
if (pos.Value() <= range->Start().Value()) return range;
+ // We can't properly connect liveranges if split occured at the end
+ // of control instruction.
+ ASSERT(pos.IsInstructionStart() ||
+ !chunk_->instructions()->at(pos.InstructionIndex())->IsControl());
+
LiveRange* result = LiveRangeFor(next_virtual_register_++);
range->SplitAt(pos, result);
return result;
diff --git a/deps/v8/src/messages.cc b/deps/v8/src/messages.cc
index 42fc3c9bd..432364919 100644
--- a/deps/v8/src/messages.cc
+++ b/deps/v8/src/messages.cc
@@ -62,67 +62,45 @@ void MessageHandler::ReportMessage(const char* msg) {
}
-Handle<Object> MessageHandler::MakeMessageObject(
+Handle<JSMessageObject> MessageHandler::MakeMessageObject(
const char* type,
MessageLocation* loc,
Vector< Handle<Object> > args,
Handle<String> stack_trace,
Handle<JSArray> stack_frames) {
- // Build error message object
- v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom.
- Handle<Object> type_str = Factory::LookupAsciiSymbol(type);
- Handle<Object> array = Factory::NewJSArray(args.length());
- for (int i = 0; i < args.length(); i++)
- SetElement(Handle<JSArray>::cast(array), i, args[i]);
-
- Handle<JSFunction> fun(Top::global_context()->make_message_fun());
- int start, end;
- Handle<Object> script;
+ Handle<String> type_handle = Factory::LookupAsciiSymbol(type);
+ Handle<JSArray> arguments_handle = Factory::NewJSArray(args.length());
+ for (int i = 0; i < args.length(); i++) {
+ SetElement(arguments_handle, i, args[i]);
+ }
+
+ int start = 0;
+ int end = 0;
+ Handle<Object> script_handle = Factory::undefined_value();
if (loc) {
start = loc->start_pos();
end = loc->end_pos();
- script = GetScriptWrapper(loc->script());
- } else {
- start = end = 0;
- script = Factory::undefined_value();
+ script_handle = GetScriptWrapper(loc->script());
}
- Handle<Object> start_handle(Smi::FromInt(start));
- Handle<Object> end_handle(Smi::FromInt(end));
- Handle<Object> stack_trace_val = stack_trace.is_null()
- ? Factory::undefined_value()
- : Handle<Object>::cast(stack_trace);
- Handle<Object> stack_frames_val = stack_frames.is_null()
- ? Factory::undefined_value()
- : Handle<Object>::cast(stack_frames);
- const int argc = 7;
- Object** argv[argc] = { type_str.location(),
- array.location(),
- start_handle.location(),
- end_handle.location(),
- script.location(),
- stack_trace_val.location(),
- stack_frames_val.location() };
-
- // Setup a catch handler to catch exceptions in creating the message. This
- // handler is non-verbose to avoid calling MakeMessage recursively in case of
- // an exception.
- v8::TryCatch catcher;
- catcher.SetVerbose(false);
- catcher.SetCaptureMessage(false);
-
- // Format the message.
- bool caught_exception = false;
- Handle<Object> message =
- Execution::Call(fun, Factory::undefined_value(), argc, argv,
- &caught_exception);
-
- // If creating the message (in JS code) resulted in an exception, we
- // skip doing the callback. This usually only happens in case of
- // stack overflow exceptions being thrown by the parser when the
- // stack is almost full.
- if (caught_exception) return Handle<Object>();
-
- return message.EscapeFrom(&scope);
+
+ Handle<Object> stack_trace_handle = stack_trace.is_null()
+ ? Factory::undefined_value()
+ : Handle<Object>::cast(stack_trace);
+
+ Handle<Object> stack_frames_handle = stack_frames.is_null()
+ ? Factory::undefined_value()
+ : Handle<Object>::cast(stack_frames);
+
+ Handle<JSMessageObject> message =
+ Factory::NewJSMessageObject(type_handle,
+ arguments_handle,
+ start,
+ end,
+ script_handle,
+ stack_trace_handle,
+ stack_frames_handle);
+
+ return message;
}
diff --git a/deps/v8/src/messages.h b/deps/v8/src/messages.h
index 440bde87e..48f324477 100644
--- a/deps/v8/src/messages.h
+++ b/deps/v8/src/messages.h
@@ -93,11 +93,12 @@ class MessageHandler {
static void ReportMessage(const char* msg);
// Returns a message object for the API to use.
- static Handle<Object> MakeMessageObject(const char* type,
- MessageLocation* loc,
- Vector< Handle<Object> > args,
- Handle<String> stack_trace,
- Handle<JSArray> stack_frames);
+ static Handle<JSMessageObject> MakeMessageObject(
+ const char* type,
+ MessageLocation* loc,
+ Vector< Handle<Object> > args,
+ Handle<String> stack_trace,
+ Handle<JSArray> stack_frames);
// Report a formatted message (needs JS allocation).
static void ReportMessage(MessageLocation* loc, Handle<Object> message);
diff --git a/deps/v8/src/messages.js b/deps/v8/src/messages.js
index fcd7285ec..4c3d1e70e 100644
--- a/deps/v8/src/messages.js
+++ b/deps/v8/src/messages.js
@@ -53,20 +53,23 @@ var kAddMessageAccessorsMarker = { };
var kMessages = 0;
var kReplacementMarkers =
- [ "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9", "%10" ];
-
-function FormatString(format, args) {
- var result = format;
- for (var i = 0; i < args.length; i++) {
- var str;
- try {
- str = ToDetailString(args[i]);
- } catch (e) {
- str = "#<error>";
+ [ "%0", "%1", "%2", "%3" ]
+
+function FormatString(format, message) {
+ var args = %MessageGetArguments(message);
+ var result = "";
+ var arg_num = 0;
+ for (var i = 0; i < format.length; i++) {
+ var str = format[i];
+ for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
+ if (format[i] !== kReplacementMarkers[arg_num]) continue;
+ try {
+ str = ToDetailString(args[arg_num]);
+ } catch (e) {
+ str = "#<error>";
+ }
}
- var replacement_marker = kReplacementMarkers[i];
- var split = %_CallFunction(result, replacement_marker, StringSplit);
- result = %_CallFunction(split, str, ArrayJoin);
+ result += str;
}
return result;
}
@@ -143,97 +146,100 @@ function FormatMessage(message) {
if (kMessages === 0) {
kMessages = {
// Error
- cyclic_proto: "Cyclic __proto__ value",
+ cyclic_proto: ["Cyclic __proto__ value"],
// TypeError
- unexpected_token: "Unexpected token %0",
- unexpected_token_number: "Unexpected number",
- unexpected_token_string: "Unexpected string",
- unexpected_token_identifier: "Unexpected identifier",
- unexpected_eos: "Unexpected end of input",
- malformed_regexp: "Invalid regular expression: /%0/: %1",
- unterminated_regexp: "Invalid regular expression: missing /",
- regexp_flags: "Cannot supply flags when constructing one RegExp from another",
- incompatible_method_receiver: "Method %0 called on incompatible receiver %1",
- invalid_lhs_in_assignment: "Invalid left-hand side in assignment",
- invalid_lhs_in_for_in: "Invalid left-hand side in for-in",
- invalid_lhs_in_postfix_op: "Invalid left-hand side expression in postfix operation",
- invalid_lhs_in_prefix_op: "Invalid left-hand side expression in prefix operation",
- multiple_defaults_in_switch: "More than one default clause in switch statement",
- newline_after_throw: "Illegal newline after throw",
- redeclaration: "%0 '%1' has already been declared",
- no_catch_or_finally: "Missing catch or finally after try",
- unknown_label: "Undefined label '%0'",
- uncaught_exception: "Uncaught %0",
- stack_trace: "Stack Trace:\n%0",
- called_non_callable: "%0 is not a function",
- undefined_method: "Object %1 has no method '%0'",
- property_not_function: "Property '%0' of object %1 is not a function",
- cannot_convert_to_primitive: "Cannot convert object to primitive value",
- not_constructor: "%0 is not a constructor",
- not_defined: "%0 is not defined",
- non_object_property_load: "Cannot read property '%0' of %1",
- non_object_property_store: "Cannot set property '%0' of %1",
- non_object_property_call: "Cannot call method '%0' of %1",
- with_expression: "%0 has no properties",
- illegal_invocation: "Illegal invocation",
- no_setter_in_callback: "Cannot set property %0 of %1 which has only a getter",
- apply_non_function: "Function.prototype.apply was called on %0, which is a %1 and not a function",
- apply_wrong_args: "Function.prototype.apply: Arguments list has wrong type",
- invalid_in_operator_use: "Cannot use 'in' operator to search for '%0' in %1",
- instanceof_function_expected: "Expecting a function in instanceof check, but got %0",
- instanceof_nonobject_proto: "Function has non-object prototype '%0' in instanceof check",
- null_to_object: "Cannot convert null to object",
- reduce_no_initial: "Reduce of empty array with no initial value",
- getter_must_be_callable: "Getter must be a function: %0",
- setter_must_be_callable: "Setter must be a function: %0",
- value_and_accessor: "Invalid property. A property cannot both have accessors and be writable or have a value: %0",
- proto_object_or_null: "Object prototype may only be an Object or null",
- property_desc_object: "Property description must be an object: %0",
- redefine_disallowed: "Cannot redefine property: %0",
- define_disallowed: "Cannot define property, object is not extensible: %0",
+ unexpected_token: ["Unexpected token ", "%0"],
+ unexpected_token_number: ["Unexpected number"],
+ unexpected_token_string: ["Unexpected string"],
+ unexpected_token_identifier: ["Unexpected identifier"],
+ unexpected_eos: ["Unexpected end of input"],
+ malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"],
+ unterminated_regexp: ["Invalid regular expression: missing /"],
+ regexp_flags: ["Cannot supply flags when constructing one RegExp from another"],
+ incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
+ invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
+ invalid_lhs_in_for_in: ["Invalid left-hand side in for-in"],
+ invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"],
+ invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
+ multiple_defaults_in_switch: ["More than one default clause in switch statement"],
+ newline_after_throw: ["Illegal newline after throw"],
+ redeclaration: ["%0", " '", "%1", "' has already been declared"],
+ no_catch_or_finally: ["Missing catch or finally after try"],
+ unknown_label: ["Undefined label '", "%0", "'"],
+ uncaught_exception: ["Uncaught ", "%0"],
+ stack_trace: ["Stack Trace:\n", "%0"],
+ called_non_callable: ["%0", " is not a function"],
+ undefined_method: ["Object ", "%1", " has no method '", "%0", "'"],
+ property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"],
+ cannot_convert_to_primitive: ["Cannot convert object to primitive value"],
+ not_constructor: ["%0", " is not a constructor"],
+ not_defined: ["%0", " is not defined"],
+ non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"],
+ non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"],
+ non_object_property_call: ["Cannot call method '", "%0", "' of ", "%1"],
+ with_expression: ["%0", " has no properties"],
+ illegal_invocation: ["Illegal invocation"],
+ no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"],
+ apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"],
+ apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"],
+ invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
+ instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"],
+ instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"],
+ null_to_object: ["Cannot convert null to object"],
+ reduce_no_initial: ["Reduce of empty array with no initial value"],
+ getter_must_be_callable: ["Getter must be a function: ", "%0"],
+ setter_must_be_callable: ["Setter must be a function: ", "%0"],
+ value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value: ", "%0"],
+ proto_object_or_null: ["Object prototype may only be an Object or null"],
+ property_desc_object: ["Property description must be an object: ", "%0"],
+ redefine_disallowed: ["Cannot redefine property: ", "%0"],
+ define_disallowed: ["Cannot define property, object is not extensible: ", "%0"],
// RangeError
- invalid_array_length: "Invalid array length",
- stack_overflow: "Maximum call stack size exceeded",
+ invalid_array_length: ["Invalid array length"],
+ stack_overflow: ["Maximum call stack size exceeded"],
// SyntaxError
- unable_to_parse: "Parse error",
- duplicate_regexp_flag: "Duplicate RegExp flag %0",
- invalid_regexp: "Invalid RegExp pattern /%0/",
- illegal_break: "Illegal break statement",
- illegal_continue: "Illegal continue statement",
- illegal_return: "Illegal return statement",
- error_loading_debugger: "Error loading debugger",
- no_input_to_regexp: "No input to %0",
- invalid_json: "String '%0' is not valid JSON",
- circular_structure: "Converting circular structure to JSON",
- obj_ctor_property_non_object: "Object.%0 called on non-object",
- array_indexof_not_defined: "Array.getIndexOf: Argument undefined",
- object_not_extensible: "Can't add property %0, object is not extensible",
- illegal_access: "Illegal access",
- invalid_preparser_data: "Invalid preparser data for function %0",
- strict_mode_with: "Strict mode code may not include a with statement",
- strict_catch_variable: "Catch variable may not be eval or arguments in strict mode",
- strict_param_name: "Parameter name eval or arguments is not allowed in strict mode",
- strict_param_dupe: "Strict mode function may not have duplicate parameter names",
- strict_var_name: "Variable name may not be eval or arguments in strict mode",
- strict_function_name: "Function name may not be eval or arguments in strict mode",
- strict_octal_literal: "Octal literals are not allowed in strict mode.",
- strict_duplicate_property: "Duplicate data property in object literal not allowed in strict mode",
- accessor_data_property: "Object literal may not have data and accessor property with the same name",
- accessor_get_set: "Object literal may not have multiple get/set accessors with the same name",
- strict_lhs_eval_assignment: "Assignment to eval or arguments is not allowed in strict mode",
- strict_lhs_postfix: "Postfix increment/decrement may not have eval or arguments operand in strict mode",
- strict_lhs_prefix: "Prefix increment/decrement may not have eval or arguments operand in strict mode",
+ unable_to_parse: ["Parse error"],
+ duplicate_regexp_flag: ["Duplicate RegExp flag ", "%0"],
+ invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
+ illegal_break: ["Illegal break statement"],
+ illegal_continue: ["Illegal continue statement"],
+ illegal_return: ["Illegal return statement"],
+ error_loading_debugger: ["Error loading debugger"],
+ no_input_to_regexp: ["No input to ", "%0"],
+ invalid_json: ["String '", "%0", "' is not valid JSON"],
+ circular_structure: ["Converting circular structure to JSON"],
+ obj_ctor_property_non_object: ["Object.", "%0", " called on non-object"],
+ array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"],
+ object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"],
+ illegal_access: ["Illegal access"],
+ invalid_preparser_data: ["Invalid preparser data for function ", "%0"],
+ strict_mode_with: ["Strict mode code may not include a with statement"],
+ strict_catch_variable: ["Catch variable may not be eval or arguments in strict mode"],
+ strict_param_name: ["Parameter name eval or arguments is not allowed in strict mode"],
+ strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
+ strict_var_name: ["Variable name may not be eval or arguments in strict mode"],
+ strict_function_name: ["Function name may not be eval or arguments in strict mode"],
+ strict_octal_literal: ["Octal literals are not allowed in strict mode."],
+ strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"],
+ accessor_data_property: ["Object literal may not have data and accessor property with the same name"],
+ accessor_get_set: ["Object literal may not have multiple get/set accessors with the same name"],
+ strict_lhs_assignment: ["Assignment to eval or arguments is not allowed in strict mode"],
+ strict_lhs_postfix: ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
+ strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
};
}
- var format = kMessages[message.type];
- if (!format) return "<unknown message " + message.type + ">";
- return FormatString(format, message.args);
+ var message_type = %MessageGetType(message);
+ var format = kMessages[message_type];
+ if (!format) return "<unknown message " + message_type + ">";
+ return FormatString(format, message);
}
function GetLineNumber(message) {
- if (message.startPos == -1) return kNoLineNumberInfo;
- var location = message.script.locationFromPosition(message.startPos, true);
+ var start_position = %MessageGetStartPosition(message);
+ if (start_position == -1) return kNoLineNumberInfo;
+ var script = %MessageGetScript(message);
+ var location = script.locationFromPosition(start_position, true);
if (location == null) return kNoLineNumberInfo;
return location.line + 1;
}
@@ -242,7 +248,9 @@ function GetLineNumber(message) {
// Returns the source code line containing the given source
// position, or the empty string if the position is invalid.
function GetSourceLine(message) {
- var location = message.script.locationFromPosition(message.startPos, true);
+ var script = %MessageGetScript(message);
+ var start_position = %MessageGetStartPosition(message);
+ var location = script.locationFromPosition(start_position, true);
if (location == null) return "";
location.restrict();
return location.sourceText();
@@ -621,29 +629,12 @@ SourceSlice.prototype.sourceText = function () {
// Returns the offset of the given position within the containing
// line.
function GetPositionInLine(message) {
- var location = message.script.locationFromPosition(message.startPos, false);
+ var script = %MessageGetScript(message);
+ var start_position = %MessageGetStartPosition(message);
+ var location = script.locationFromPosition(start_position, false);
if (location == null) return -1;
location.restrict();
- return message.startPos - location.start;
-}
-
-
-function ErrorMessage(type, args, startPos, endPos, script, stackTrace,
- stackFrames) {
- this.startPos = startPos;
- this.endPos = endPos;
- this.type = type;
- this.args = args;
- this.script = script;
- this.stackTrace = stackTrace;
- this.stackFrames = stackFrames;
-}
-
-
-function MakeMessage(type, args, startPos, endPos, script, stackTrace,
- stackFrames) {
- return new ErrorMessage(type, args, startPos, endPos, script, stackTrace,
- stackFrames);
+ return start_position - location.start;
}
@@ -990,7 +981,7 @@ function DefineError(f) {
// DefineOneShotAccessor always inserts a message property and
// ignores setters.
DefineOneShotAccessor(this, 'message', function (obj) {
- return FormatMessage({type: obj.type, args: obj.arguments});
+ return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
});
} else if (!IS_UNDEFINED(m)) {
%IgnoreAttributesAndSetProperty(this, 'message', ToString(m));
@@ -1004,11 +995,12 @@ function DefineError(f) {
function captureStackTrace(obj, cons_opt) {
var stackTraceLimit = $Error.stackTraceLimit;
- if (!stackTraceLimit) return;
+ if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
if (stackTraceLimit < 0 || stackTraceLimit > 10000)
stackTraceLimit = 10000;
- var raw_stack = %CollectStackTrace(cons_opt ? cons_opt : captureStackTrace,
- stackTraceLimit);
+ var raw_stack = %CollectStackTrace(cons_opt
+ ? cons_opt
+ : captureStackTrace, stackTraceLimit);
DefineOneShotAccessor(obj, 'stack', function (obj) {
return FormatRawStackTrace(obj, raw_stack);
});
@@ -1038,14 +1030,16 @@ function errorToStringDetectCycle() {
if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker;
try {
var type = this.type;
- if (type && !this.hasOwnProperty("message")) {
- var formatted = FormatMessage({ type: type, args: this.arguments });
+ if (type && !%_CallFunction(this, "message", ObjectHasOwnProperty)) {
+ var formatted = FormatMessage(%NewMessageObject(type, this.arguments));
return this.name + ": " + formatted;
}
- var message = this.hasOwnProperty("message") ? (": " + this.message) : "";
+ var message = %_CallFunction(this, "message", ObjectHasOwnProperty)
+ ? (": " + this.message)
+ : "";
return this.name + message;
} finally {
- visited_errors.pop();
+ visited_errors.length = visited_errors.length - 1;
}
}
diff --git a/deps/v8/src/mirror-debugger.js b/deps/v8/src/mirror-debugger.js
index 80d385952..416f88794 100644
--- a/deps/v8/src/mirror-debugger.js
+++ b/deps/v8/src/mirror-debugger.js
@@ -1084,9 +1084,9 @@ ErrorMirror.prototype.toText = function() {
// Use the same text representation as in messages.js.
var text;
try {
- str = builtins.ToDetailString(this.value_);
+ str = %_CallFunction(this.value_, builtins.errorToString);
} catch (e) {
- str = '#<an Error>';
+ str = '#<Error>';
}
return str;
}
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
index f9c57e696..c8246c86c 100644
--- a/deps/v8/src/objects-debug.cc
+++ b/deps/v8/src/objects-debug.cc
@@ -158,6 +158,9 @@ void HeapObject::HeapObjectVerify() {
case SHARED_FUNCTION_INFO_TYPE:
SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
break;
+ case JS_MESSAGE_OBJECT_TYPE:
+ JSMessageObject::cast(this)->JSMessageObjectVerify();
+ break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
@@ -296,6 +299,19 @@ void JSValue::JSValueVerify() {
}
+void JSMessageObject::JSMessageObjectVerify() {
+ CHECK(IsJSMessageObject());
+ CHECK(type()->IsString());
+ CHECK(arguments()->IsJSArray());
+ VerifyObjectField(kStartPositionOffset);
+ VerifyObjectField(kEndPositionOffset);
+ VerifyObjectField(kArgumentsOffset);
+ VerifyObjectField(kScriptOffset);
+ VerifyObjectField(kStackTraceOffset);
+ VerifyObjectField(kStackFramesOffset);
+}
+
+
void String::StringVerify() {
CHECK(IsString());
CHECK(length() >= 0 && length() <= Smi::kMaxValue);
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index db9e2ef7b..50f4031b7 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -408,7 +408,7 @@ bool MaybeObject::IsRetryAfterGC() {
bool MaybeObject::IsOutOfMemory() {
return HAS_FAILURE_TAG(this)
- && Failure::cast(this)->IsOutOfMemoryException();
+ && Failure::cast(this)->IsOutOfMemoryException();
}
@@ -430,26 +430,26 @@ Failure* Failure::cast(MaybeObject* obj) {
bool Object::IsJSObject() {
return IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
}
bool Object::IsJSContextExtensionObject() {
return IsHeapObject()
- && (HeapObject::cast(this)->map()->instance_type() ==
- JS_CONTEXT_EXTENSION_OBJECT_TYPE);
+ && (HeapObject::cast(this)->map()->instance_type() ==
+ JS_CONTEXT_EXTENSION_OBJECT_TYPE);
}
bool Object::IsMap() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
}
bool Object::IsFixedArray() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
}
@@ -495,19 +495,19 @@ bool Object::IsContext() {
bool Object::IsCatchContext() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map() == Heap::catch_context_map();
+ && HeapObject::cast(this)->map() == Heap::catch_context_map();
}
bool Object::IsGlobalContext() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map() == Heap::global_context_map();
+ && HeapObject::cast(this)->map() == Heap::global_context_map();
}
bool Object::IsJSFunction() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
}
@@ -518,7 +518,7 @@ template <> inline bool Is<JSFunction>(Object* obj) {
bool Object::IsCode() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
}
@@ -544,7 +544,14 @@ bool Object::IsSharedFunctionInfo() {
bool Object::IsJSValue() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
+}
+
+
+bool Object::IsJSMessageObject() {
+ return Object::IsHeapObject()
+ && (HeapObject::cast(this)->map()->instance_type() ==
+ JS_MESSAGE_OBJECT_TYPE);
}
@@ -555,7 +562,7 @@ bool Object::IsStringWrapper() {
bool Object::IsProxy() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
}
@@ -566,13 +573,13 @@ bool Object::IsBoolean() {
bool Object::IsJSArray() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
}
bool Object::IsJSRegExp() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
}
@@ -583,7 +590,7 @@ template <> inline bool Is<JSArray>(Object* obj) {
bool Object::IsHashTable() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map() == Heap::hash_table_map();
+ && HeapObject::cast(this)->map() == Heap::hash_table_map();
}
@@ -1285,6 +1292,8 @@ int JSObject::GetHeaderSize() {
return JSValue::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return JSObject::kHeaderSize;
+ case JS_MESSAGE_OBJECT_TYPE:
+ return JSMessageObject::kSize;
default:
UNREACHABLE();
return 0;
@@ -3289,6 +3298,22 @@ JSValue* JSValue::cast(Object* obj) {
}
+ACCESSORS(JSMessageObject, type, String, kTypeOffset)
+ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
+ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
+ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
+ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
+SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
+SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
+
+
+JSMessageObject* JSMessageObject::cast(Object* obj) {
+ ASSERT(obj->IsJSMessageObject());
+ ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
+ return reinterpret_cast<JSMessageObject*>(obj);
+}
+
+
INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
diff --git a/deps/v8/src/objects-printer.cc b/deps/v8/src/objects-printer.cc
index 9f05b0f62..237358dcc 100644
--- a/deps/v8/src/objects-printer.cc
+++ b/deps/v8/src/objects-printer.cc
@@ -151,6 +151,9 @@ void HeapObject::HeapObjectPrint(FILE* out) {
case SHARED_FUNCTION_INFO_TYPE:
SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
break;
+ case JS_MESSAGE_OBJECT_TYPE:
+ JSMessageObject::cast(this)->JSMessageObjectPrint(out);
+ break;
case JS_GLOBAL_PROPERTY_CELL_TYPE:
JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
break;
@@ -396,6 +399,7 @@ static const char* TypeToString(InstanceType type) {
case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
case PROXY_TYPE: return "PROXY";
case LAST_STRING_TYPE: return "LAST_STRING_TYPE";
+ case JS_MESSAGE_OBJECT_TYPE: return "JS_MESSAGE_OBJECT_TYPE";
#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
@@ -466,6 +470,24 @@ void JSValue::JSValuePrint(FILE* out) {
}
+void JSMessageObject::JSMessageObjectPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSMessageObject");
+ PrintF(out, " - type: ");
+ type()->ShortPrint(out);
+ PrintF(out, "\n - arguments: ");
+ arguments()->ShortPrint(out);
+ PrintF(out, "\n - start_position: %d", start_position());
+ PrintF(out, "\n - end_position: %d", end_position());
+ PrintF(out, "\n - script: ");
+ script()->ShortPrint(out);
+ PrintF(out, "\n - stack_trace: ");
+ stack_trace()->ShortPrint(out);
+ PrintF(out, "\n - stack_frames: ");
+ stack_frames()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
void String::StringPrint(FILE* out) {
if (StringShape(this).IsSymbol()) {
PrintF(out, "#");
diff --git a/deps/v8/src/objects-visiting.cc b/deps/v8/src/objects-visiting.cc
index c35e02cc9..5f054bd32 100644
--- a/deps/v8/src/objects-visiting.cc
+++ b/deps/v8/src/objects-visiting.cc
@@ -104,6 +104,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
+ case JS_MESSAGE_OBJECT_TYPE:
return GetVisitorIdForSize(kVisitJSObject,
kVisitJSObjectGeneric,
instance_size);
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 36a8e5c2a..8bced586b 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -979,6 +979,9 @@ void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
case SHARED_FUNCTION_INFO_TYPE:
accumulator->Add("<SharedFunctionInfo>");
break;
+ case JS_MESSAGE_OBJECT_TYPE:
+ accumulator->Add("<JSMessageObject>");
+ break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
accumulator->Put('<'); \
@@ -1069,6 +1072,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
+ case JS_MESSAGE_OBJECT_TYPE:
JSObject::BodyDescriptor::IterateBody(this, object_size, v);
break;
case JS_FUNCTION_TYPE:
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 8c63022db..c9b3757df 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -54,7 +54,8 @@
// - JSGlobalObject
// - JSBuiltinsObject
// - JSGlobalProxy
-// - JSValue
+// - JSValue
+// - JSMessageObject
// - ByteArray
// - PixelArray
// - ExternalArray
@@ -288,6 +289,8 @@ static const int kVariableSizeSentinel = 0;
V(FIXED_ARRAY_TYPE) \
V(SHARED_FUNCTION_INFO_TYPE) \
\
+ V(JS_MESSAGE_OBJECT_TYPE) \
+ \
V(JS_VALUE_TYPE) \
V(JS_OBJECT_TYPE) \
V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
@@ -518,6 +521,8 @@ enum InstanceType {
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
+ JS_MESSAGE_OBJECT_TYPE,
+
JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
JS_OBJECT_TYPE,
JS_CONTEXT_EXTENSION_OBJECT_TYPE,
@@ -675,6 +680,7 @@ class MaybeObject BASE_EMBEDDED {
V(Oddball) \
V(SharedFunctionInfo) \
V(JSValue) \
+ V(JSMessageObject) \
V(StringWrapper) \
V(Proxy) \
V(Boolean) \
@@ -4696,6 +4702,68 @@ class JSValue: public JSObject {
DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
};
+
+// Representation of message objects used for error reporting through
+// the API. The messages are formatted in JavaScript so this object is
+// a real JavaScript object. The information used for formatting the
+// error messages are not directly accessible from JavaScript to
+// prevent leaking information to user code called during error
+// formatting.
+class JSMessageObject: public JSObject {
+ public:
+ // [type]: the type of error message.
+ DECL_ACCESSORS(type, String)
+
+ // [arguments]: the arguments for formatting the error message.
+ DECL_ACCESSORS(arguments, JSArray)
+
+ // [script]: the script from which the error message originated.
+ DECL_ACCESSORS(script, Object)
+
+ // [stack_trace]: the stack trace for this error message.
+ DECL_ACCESSORS(stack_trace, Object)
+
+ // [stack_frames]: an array of stack frames for this error object.
+ DECL_ACCESSORS(stack_frames, Object)
+
+ // [start_position]: the start position in the script for the error message.
+ inline int start_position();
+ inline void set_start_position(int value);
+
+ // [end_position]: the end position in the script for the error message.
+ inline int end_position();
+ inline void set_end_position(int value);
+
+ // Casting.
+ static inline JSMessageObject* cast(Object* obj);
+
+ // Dispatched behavior.
+#ifdef OBJECT_PRINT
+ inline void JSMessageObjectPrint() {
+ JSMessageObjectPrint(stdout);
+ }
+ void JSMessageObjectPrint(FILE* out);
+#endif
+#ifdef DEBUG
+ void JSMessageObjectVerify();
+#endif
+
+ // Layout description.
+ static const int kTypeOffset = JSObject::kHeaderSize;
+ static const int kArgumentsOffset = kTypeOffset + kPointerSize;
+ static const int kScriptOffset = kArgumentsOffset + kPointerSize;
+ static const int kStackTraceOffset = kScriptOffset + kPointerSize;
+ static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
+ static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
+ static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
+ static const int kSize = kEndPositionOffset + kPointerSize;
+
+ typedef FixedBodyDescriptor<HeapObject::kMapOffset,
+ kStackFramesOffset + kPointerSize,
+ kSize> BodyDescriptor;
+};
+
+
// Regular expressions
// The regular expression holds a single reference to a FixedArray in
// the kDataOffset field.
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index c0976988e..ccb3f64e1 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -3035,7 +3035,7 @@ Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
// Defined in ast.cc
bool IsEqualString(void* first, void* second);
-bool IsEqualSmi(void* first, void* second);
+bool IsEqualNumber(void* first, void* second);
// Validation per 11.1.5 Object Initialiser
@@ -3043,7 +3043,7 @@ class ObjectLiteralPropertyChecker {
public:
ObjectLiteralPropertyChecker(Parser* parser, bool strict) :
props(&IsEqualString),
- elems(&IsEqualSmi),
+ elems(&IsEqualNumber),
parser_(parser),
strict_(strict) {
}
@@ -3092,13 +3092,12 @@ void ObjectLiteralPropertyChecker::CheckProperty(
uint32_t hash;
HashMap* map;
void* key;
- Smi* smi_key_location;
if (handle->IsSymbol()) {
Handle<String> name(String::cast(*handle));
if (name->AsArrayIndex(&hash)) {
- smi_key_location = Smi::FromInt(hash);
- key = &smi_key_location;
+ Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
+ key = key_handle.location();
map = &elems;
} else {
key = handle.location();
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 96d07a859..d55a201e5 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -10748,6 +10748,45 @@ static MaybeObject* Runtime_GetFromCache(Arguments args) {
return *value;
}
+
+static MaybeObject* Runtime_NewMessageObject(Arguments args) {
+ HandleScope scope;
+ CONVERT_ARG_CHECKED(String, type, 0);
+ CONVERT_ARG_CHECKED(JSArray, arguments, 1);
+ return *Factory::NewJSMessageObject(type,
+ arguments,
+ 0,
+ 0,
+ Factory::undefined_value(),
+ Factory::undefined_value(),
+ Factory::undefined_value());
+}
+
+
+static MaybeObject* Runtime_MessageGetType(Arguments args) {
+ CONVERT_CHECKED(JSMessageObject, message, args[0]);
+ return message->type();
+}
+
+
+static MaybeObject* Runtime_MessageGetArguments(Arguments args) {
+ CONVERT_CHECKED(JSMessageObject, message, args[0]);
+ return message->arguments();
+}
+
+
+static MaybeObject* Runtime_MessageGetStartPosition(Arguments args) {
+ CONVERT_CHECKED(JSMessageObject, message, args[0]);
+ return Smi::FromInt(message->start_position());
+}
+
+
+static MaybeObject* Runtime_MessageGetScript(Arguments args) {
+ CONVERT_CHECKED(JSMessageObject, message, args[0]);
+ return message->script();
+}
+
+
#ifdef DEBUG
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
// Exclude the code in release mode.
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index d8b34570c..b201eb861 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -310,6 +310,13 @@ namespace internal {
/* Cache suport */ \
F(GetFromCache, 2, 1) \
\
+ /* Message objects */ \
+ F(NewMessageObject, 2, 1) \
+ F(MessageGetType, 1, 1) \
+ F(MessageGetArguments, 1, 1) \
+ F(MessageGetStartPosition, 1, 1) \
+ F(MessageGetScript, 1, 1) \
+ \
/* Pseudo functions - handled as macros by parser */ \
F(IS_VAR, 1, 1)
diff --git a/deps/v8/src/safepoint-table.cc b/deps/v8/src/safepoint-table.cc
index 153bf4327..34e9cf4ab 100644
--- a/deps/v8/src/safepoint-table.cc
+++ b/deps/v8/src/safepoint-table.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -27,6 +27,7 @@
#include "safepoint-table.h"
+#include "deoptimizer.h"
#include "disasm.h"
#include "macro-assembler.h"
@@ -144,6 +145,14 @@ unsigned SafepointTableBuilder::GetCodeOffset() const {
void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
+ // For lazy deoptimization we need space to patch a call after every call.
+ // Ensure there is always space for such patching, even if the code ends
+ // in a call.
+ int target_offset = assembler->pc_offset() + Deoptimizer::patch_size();
+ while (assembler->pc_offset() < target_offset) {
+ assembler->nop();
+ }
+
// Make sure the safepoint table is properly aligned. Pad with nops.
assembler->Align(kIntSize);
assembler->RecordComment(";;; Safepoint table.");
diff --git a/deps/v8/src/safepoint-table.h b/deps/v8/src/safepoint-table.h
index fa3590511..eeeae37fb 100644
--- a/deps/v8/src/safepoint-table.h
+++ b/deps/v8/src/safepoint-table.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -215,11 +215,10 @@ class SafepointTableBuilder BASE_EMBEDDED {
unsigned GetCodeOffset() const;
// Define a new safepoint for the current position in the body.
- Safepoint DefineSafepoint(
- Assembler* assembler,
- Safepoint::Kind kind,
- int arguments,
- int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
+ Safepoint DefineSafepoint(Assembler* assembler,
+ Safepoint::Kind kind,
+ int arguments,
+ int deoptimization_index);
// Update the last safepoint with the size of the code generated for the gap
// following it.
diff --git a/deps/v8/src/scanner-base.cc b/deps/v8/src/scanner-base.cc
index e141d0eb7..fe33f38e7 100644
--- a/deps/v8/src/scanner-base.cc
+++ b/deps/v8/src/scanner-base.cc
@@ -99,9 +99,9 @@ uc32 Scanner::ScanHexEscape(uc32 c, int length) {
// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
// ECMA-262. Other JS VMs support them.
uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
- octal_pos_ = source_pos() - 1; // Already advanced
uc32 x = c - '0';
- for (int i = 0; i < length; i++) {
+ int i = 0;
+ for (; i < length; i++) {
int d = c0_ - '0';
if (d < 0 || d > 7) break;
int nx = x * 8 + d;
@@ -109,6 +109,12 @@ uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
x = nx;
Advance();
}
+ // Anything excelt '\0' is an octal escape sequence, illegal in strict mode.
+ // Remember the position of octal escape sequences so that better error
+ // can be reported later (in strict mode).
+ if (c != '0' || i > 0) {
+ octal_pos_ = source_pos() - i - 1; // Already advanced
+ }
return x;
}
diff --git a/deps/v8/src/scanner-base.h b/deps/v8/src/scanner-base.h
index 3d9800f02..7ac1d358e 100644
--- a/deps/v8/src/scanner-base.h
+++ b/deps/v8/src/scanner-base.h
@@ -409,6 +409,8 @@ class Scanner {
}
uc32 ScanHexEscape(uc32 c, int length);
+
+ // Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
uc32 ScanOctalEscape(uc32 c, int length);
// Return the current source position.
diff --git a/deps/v8/src/utils.h b/deps/v8/src/utils.h
index 21e70d758..219343b7f 100644
--- a/deps/v8/src/utils.h
+++ b/deps/v8/src/utils.h
@@ -760,20 +760,32 @@ static inline int TenToThe(int exponent) {
// you can use BitCast to cast one pointer type to another. This confuses gcc
// enough that it can no longer see that you have cast one pointer type to
// another thus avoiding the warning.
+
+// We need different implementations of BitCast for pointer and non-pointer
+// values. We use partial specialization of auxiliary struct to work around
+// issues with template functions overloading.
template <class Dest, class Source>
-inline Dest BitCast(const Source& source) {
- // Compile time assertion: sizeof(Dest) == sizeof(Source)
- // A compile error here means your Dest and Source have different sizes.
- typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+struct BitCastHelper {
+ STATIC_ASSERT(sizeof(Dest) == sizeof(Source));
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
+ INLINE(static Dest cast(const Source& source)) {
+ Dest dest;
+ memcpy(&dest, &source, sizeof(dest));
+ return dest;
+ }
+};
template <class Dest, class Source>
-inline Dest BitCast(Source* source) {
- return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
+struct BitCastHelper<Dest, Source*> {
+ INLINE(static Dest cast(Source* source)) {
+ return BitCastHelper<Dest, uintptr_t>::
+ cast(reinterpret_cast<uintptr_t>(source));
+ }
+};
+
+template <class Dest, class Source>
+inline Dest BitCast(const Source& source) {
+ return BitCastHelper<Dest, Source>::cast(source);
}
} } // namespace v8::internal
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 0a43561db..e17f78047 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 1
-#define BUILD_NUMBER 0
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 1
+#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index bebe4682d..91686f920 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -6969,10 +6969,12 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ j(not_equal, &not_minus_half);
// Calculates reciprocal of square root.
- // Note that 1/sqrt(x) = sqrt(1/x))
- __ divsd(xmm3, xmm0);
- __ movsd(xmm1, xmm3);
+ // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
+ __ xorpd(xmm1, xmm1);
+ __ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
+ __ divsd(xmm3, xmm1);
+ __ movsd(xmm1, xmm3);
__ jmp(&allocate_return);
// Test for 0.5.
@@ -6985,7 +6987,9 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
call_runtime.Branch(not_equal);
// Calculates square root.
- __ movsd(xmm1, xmm0);
+ // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
+ __ xorpd(xmm1, xmm1);
+ __ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
JumpTarget done;
diff --git a/deps/v8/src/x64/deoptimizer-x64.cc b/deps/v8/src/x64/deoptimizer-x64.cc
index 60d46ef2b..29b9023d4 100644
--- a/deps/v8/src/x64/deoptimizer-x64.cc
+++ b/deps/v8/src/x64/deoptimizer-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -40,6 +40,12 @@ namespace internal {
int Deoptimizer::table_entry_size_ = 10;
+
+int Deoptimizer::patch_size() {
+ return Assembler::kCallInstructionLength;
+}
+
+
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
AssertNoAllocation no_allocation;
@@ -72,12 +78,12 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
#endif
last_pc_offset = pc_offset;
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- CodePatcher patcher(
- code->instruction_start() + pc_offset + gap_code_size,
- Assembler::kCallInstructionLength);
+ last_pc_offset += gap_code_size;
+ CodePatcher patcher(code->instruction_start() + last_pc_offset,
+ patch_size());
patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY),
RelocInfo::NONE);
- last_pc_offset += gap_code_size + Assembler::kCallInstructionLength;
+ last_pc_offset += patch_size();
}
}
#ifdef DEBUG
@@ -107,16 +113,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
}
-void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
- Code* check_code,
- Code* replacement_code) {
+void Deoptimizer::PatchStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code) {
UNIMPLEMENTED();
}
-void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
- Code* check_code,
- Code* replacement_code) {
+void Deoptimizer::RevertStackCheckCodeAt(Address pc_after,
+ Code* check_code,
+ Code* replacement_code) {
UNIMPLEMENTED();
}
diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc
index 513c98407..4f1efc480 100644
--- a/deps/v8/src/x64/lithium-codegen-x64.cc
+++ b/deps/v8/src/x64/lithium-codegen-x64.cc
@@ -346,17 +346,11 @@ void LCodeGen::AddToTranslation(Translation* translation,
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
- if (instr != NULL) {
- LPointerMap* pointers = instr->pointer_map();
- RecordPosition(pointers->position());
- __ call(code, mode);
- RegisterLazyDeoptimization(instr);
- } else {
- LPointerMap no_pointers(0);
- RecordPosition(no_pointers.position());
- __ call(code, mode);
- RecordSafepoint(&no_pointers, Safepoint::kNoDeoptimizationIndex);
- }
+ ASSERT(instr != NULL);
+ LPointerMap* pointers = instr->pointer_map();
+ RecordPosition(pointers->position());
+ __ call(code, mode);
+ RegisterLazyDeoptimization(instr);
// Signal that we don't inline smi code before these stubs in the
// optimizing code generator.
diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc
index 2dd5cf733..0a52c6da1 100644
--- a/deps/v8/src/x64/lithium-x64.cc
+++ b/deps/v8/src/x64/lithium-x64.cc
@@ -653,16 +653,16 @@ LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
LInstruction* instr, int ast_id) {
- ASSERT(instructions_pending_deoptimization_environment_ == NULL);
+ ASSERT(instruction_pending_deoptimization_environment_ == NULL);
ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
- instructions_pending_deoptimization_environment_ = instr;
+ instruction_pending_deoptimization_environment_ = instr;
pending_deoptimization_ast_id_ = ast_id;
return instr;
}
void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
- instructions_pending_deoptimization_environment_ = NULL;
+ instruction_pending_deoptimization_environment_ = NULL;
pending_deoptimization_ast_id_ = AstNode::kNoNumber;
}
@@ -1328,6 +1328,13 @@ LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
}
+LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
+ // The control instruction marking the end of a block that completed
+ // abruptly (e.g., threw an exception). There is nothing specific to do.
+ return NULL;
+}
+
+
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
Abort("Unimplemented: %s", "DoThrow");
return NULL;
@@ -1663,7 +1670,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
if (pending_deoptimization_ast_id_ == instr->ast_id()) {
LLazyBailout* lazy_bailout = new LLazyBailout;
LInstruction* result = AssignEnvironment(lazy_bailout);
- instructions_pending_deoptimization_environment_->
+ instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
ClearInstructionPendingDeoptimizationEnvironment();
return result;
diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h
index 319579165..abeb2a360 100644
--- a/deps/v8/src/x64/lithium-x64.h
+++ b/deps/v8/src/x64/lithium-x64.h
@@ -1847,7 +1847,7 @@ class LChunkBuilder BASE_EMBEDDED {
argument_count_(0),
allocator_(allocator),
position_(RelocInfo::kNoPosition),
- instructions_pending_deoptimization_environment_(NULL),
+ instruction_pending_deoptimization_environment_(NULL),
pending_deoptimization_ast_id_(AstNode::kNoNumber) { }
// Build the sequence for the graph.
@@ -1981,7 +1981,7 @@ class LChunkBuilder BASE_EMBEDDED {
int argument_count_;
LAllocator* allocator_;
int position_;
- LInstruction* instructions_pending_deoptimization_environment_;
+ LInstruction* instruction_pending_deoptimization_environment_;
int pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status
index 1009f85c0..d7e446d1c 100644
--- a/deps/v8/test/cctest/cctest.status
+++ b/deps/v8/test/cctest/cctest.status
@@ -29,11 +29,6 @@ prefix cctest
test-api/Bug*: FAIL
-# The problem is that a code object can get a different optimizable flag
-# in crankshaft after creation.
-test-log/EquivalenceOfLoggingAndTraversal: SKIP
-
-
##############################################################################
# BUG(281): This test fails on some Linuxes.
test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
@@ -51,9 +46,6 @@ test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL
test-serialize/TestThatAlwaysFails: FAIL
test-serialize/DependentTestThatAlwaysFails: FAIL
-# BUG(1079)
-test-api/CaptureStackTraceForUncaughtException: PASS || FAIL
-
##############################################################################
[ $arch == x64 ]
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 9b9f469f6..ee620678a 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -2369,13 +2369,30 @@ static void check_reference_error_message(
}
-// Test that overwritten toString methods are not invoked on uncaught
-// exception formatting. However, they are invoked when performing
-// normal error string conversions.
+static v8::Handle<Value> Fail(const v8::Arguments& args) {
+ ApiTestFuzzer::Fuzz();
+ CHECK(false);
+ return v8::Undefined();
+}
+
+
+// Test that overwritten methods are not invoked on uncaught exception
+// formatting. However, they are invoked when performing normal error
+// string conversions.
TEST(APIThrowMessageOverwrittenToString) {
v8::HandleScope scope;
v8::V8::AddMessageListener(check_reference_error_message);
- LocalContext context;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
+ LocalContext context(NULL, templ);
+ CompileRun("asdf;");
+ CompileRun("var limit = {};"
+ "limit.valueOf = fail;"
+ "Error.stackTraceLimit = limit;");
+ CompileRun("asdf");
+ CompileRun("Array.prototype.pop = fail;");
+ CompileRun("Object.prototype.hasOwnProperty = fail;");
+ CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
CompileRun("ReferenceError.prototype.toString ="
diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc
index 503e0cf7c..032a18366 100644
--- a/deps/v8/test/cctest/test-log.cc
+++ b/deps/v8/test/cctest/test-log.cc
@@ -1074,6 +1074,21 @@ static bool AreFuncNamesEqual(CodeEntityInfo ref_s, CodeEntityInfo new_s) {
return true;
}
}
+ // Code objects can change their optimizability: code object may start
+ // as optimizable, but later be discovered to be actually not optimizable.
+ // Alas, we don't record this info as of now, so we allow cases when
+ // ref is thought to be optimizable while traverse finds it to be
+ // not optimizable.
+ if (ref_s[1] == '~') { // Code object used to be optimizable
+ if (new_s[1] == ' ') { // ...but later was set unoptimizable.
+ CHECK_EQ('"', ref_s[0]);
+ CHECK_EQ('"', new_s[0]);
+ ref_s += 2; // Cut the leading quote and the marker
+ ref_len -= 2;
+ new_s += 1; // Cut the leading quote only.
+ new_len -= 1;
+ }
+ }
return ref_len == new_len && strncmp(ref_s, new_s, ref_len) == 0;
}
diff --git a/deps/v8/test/mjsunit/array-splice.js b/deps/v8/test/mjsunit/array-splice.js
index 68dd9b2ba..0e307b5d3 100644
--- a/deps/v8/test/mjsunit/array-splice.js
+++ b/deps/v8/test/mjsunit/array-splice.js
@@ -339,6 +339,20 @@
})();
+// Check the case of JS builtin .splice()
+(function() {
+ for (var i = 0; i < 7; i++) {
+ var array = [1, 2, 3, 4];
+ Array.prototype[3] = 'foo'; // To force JS builtin.
+
+ var spliced = array.splice();
+
+ assertEquals([], spliced);
+ assertEquals([1, 2, 3, 4], array);
+ }
+})();
+
+
// Check the behaviour when approaching maximal values for length.
(function() {
for (var i = 0; i < 7; i++) {
diff --git a/deps/v8/test/mjsunit/compiler/literals.js b/deps/v8/test/mjsunit/compiler/literals.js
index d846cf5b7..e910bb3c6 100644
--- a/deps/v8/test/mjsunit/compiler/literals.js
+++ b/deps/v8/test/mjsunit/compiler/literals.js
@@ -88,3 +88,6 @@ assertEquals(17, eval('[1,2,3,4]; 17'));
assertEquals(19, eval('var a=1, b=2; [a,b,3,4]; 19'));
assertEquals(23, eval('var a=1, b=2; c=23; [a,b,3,4]; c'));
+// Test that literals work for non-smi indices.
+// Ensure hash-map collision if using value as hash.
+var o = {"2345678901" : 42, "2345678901" : 30};
diff --git a/deps/v8/test/mjsunit/compiler/regress-1085.js b/deps/v8/test/mjsunit/compiler/regress-1085.js
new file mode 100644
index 000000000..5d787a45e
--- /dev/null
+++ b/deps/v8/test/mjsunit/compiler/regress-1085.js
@@ -0,0 +1,35 @@
+// Copyright 2011 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.
+
+
+// Test correct checks for negative zero.
+// This test relies on specific type feedback for Math.min.
+function f(x) { return 1 / Math.min(1, x); }
+
+for (var i=0; i<1000000; i++) f(1);
+
+assertEquals(-Infinity, f(-0));
diff --git a/deps/v8/test/mjsunit/math-pow.js b/deps/v8/test/mjsunit/math-pow.js
index e732955c9..30d0cbdce 100644
--- a/deps/v8/test/mjsunit/math-pow.js
+++ b/deps/v8/test/mjsunit/math-pow.js
@@ -58,10 +58,11 @@ assertEquals(Infinity, Math.pow(-1.1, Infinity));
assertEquals(Infinity, Math.pow(2, Infinity));
assertEquals(Infinity, Math.pow(-2, Infinity));
-assertEquals(+0, Math.pow(1.1, -Infinity));
-assertEquals(+0, Math.pow(-1.1, -Infinity));
-assertEquals(+0, Math.pow(2, -Infinity));
-assertEquals(+0, Math.pow(-2, -Infinity));
+// Because +0 == -0, we need to compare 1/{+,-}0 to {+,-}Infinity
+assertEquals(+Infinity, 1/Math.pow(1.1, -Infinity));
+assertEquals(+Infinity, 1/Math.pow(-1.1, -Infinity));
+assertEquals(+Infinity, 1/Math.pow(2, -Infinity));
+assertEquals(+Infinity, 1/Math.pow(-2, -Infinity));
assertEquals(NaN, Math.pow(1, Infinity));
assertEquals(NaN, Math.pow(1, -Infinity));
@@ -81,8 +82,8 @@ assertEquals(Infinity, Math.pow(-0.999, -Infinity));
assertEquals(Infinity, Math.pow(Infinity, 0.1));
assertEquals(Infinity, Math.pow(Infinity, 2));
-assertEquals(+0, Math.pow(Infinity, -0.1));
-assertEquals(+0, Math.pow(Infinity, -2));
+assertEquals(+Infinity, 1/Math.pow(Infinity, -0.1));
+assertEquals(+Infinity, 1/Math.pow(Infinity, -2));
assertEquals(-Infinity, Math.pow(-Infinity, 3));
assertEquals(-Infinity, Math.pow(-Infinity, 13));
@@ -90,23 +91,23 @@ assertEquals(-Infinity, Math.pow(-Infinity, 13));
assertEquals(Infinity, Math.pow(-Infinity, 3.1));
assertEquals(Infinity, Math.pow(-Infinity, 2));
-assertEquals(-0, Math.pow(-Infinity, -3));
-assertEquals(-0, Math.pow(-Infinity, -13));
+assertEquals(-Infinity, 1/Math.pow(-Infinity, -3));
+assertEquals(-Infinity, 1/Math.pow(-Infinity, -13));
-assertEquals(+0, Math.pow(-Infinity, -3.1));
-assertEquals(+0, Math.pow(-Infinity, -2));
+assertEquals(+Infinity, 1/Math.pow(-Infinity, -3.1));
+assertEquals(+Infinity, 1/Math.pow(-Infinity, -2));
-assertEquals(+0, Math.pow(+0, 1.1));
-assertEquals(+0, Math.pow(+0, 2));
+assertEquals(+Infinity, 1/Math.pow(+0, 1.1));
+assertEquals(+Infinity, 1/Math.pow(+0, 2));
assertEquals(Infinity, Math.pow(+0, -1.1));
assertEquals(Infinity, Math.pow(+0, -2));
-assertEquals(-0, Math.pow(-0, 3));
-assertEquals(-0, Math.pow(-0, 13));
+assertEquals(-Infinity, 1/Math.pow(-0, 3));
+assertEquals(-Infinity, 1/Math.pow(-0, 13));
-assertEquals(+0, Math.pow(-0, 3.1));
-assertEquals(+0, Math.pow(-0, 2));
+assertEquals(+Infinity, 1/Math.pow(-0, 3.1));
+assertEquals(+Infinity, 1/Math.pow(-0, 2));
assertEquals(-Infinity, Math.pow(-0, -3));
assertEquals(-Infinity, Math.pow(-0, -13));
@@ -123,6 +124,18 @@ assertEquals(NaN, Math.pow(-2, -1.1));
assertEquals(NaN, Math.pow(-1000, 1.1));
assertEquals(NaN, Math.pow(-1000, -1.1));
+assertEquals(+Infinity, 1/Math.pow(-0, 0.5));
+assertEquals(+Infinity, 1/Math.pow(-0, 0.6));
+assertEquals(-Infinity, 1/Math.pow(-0, 1));
+assertEquals(-Infinity, 1/Math.pow(-0, 10000000001));
+
+assertEquals(+Infinity, Math.pow(-0, -0.5));
+assertEquals(+Infinity, Math.pow(-0, -0.6));
+assertEquals(-Infinity, Math.pow(-0, -1));
+assertEquals(-Infinity, Math.pow(-0, -10000000001));
+
+
+
// Tests from Sputnik S8.5_A13_T1.
assertTrue((1*((Math.pow(2,53))-1)*(Math.pow(2,-1074))) === 4.4501477170144023e-308);
assertTrue((1*(Math.pow(2,52))*(Math.pow(2,-1074))) === 2.2250738585072014e-308);
diff --git a/deps/v8/test/mjsunit/mirror-error.js b/deps/v8/test/mjsunit/mirror-error.js
index 4ed8c1b42..9fea17cf1 100644
--- a/deps/v8/test/mjsunit/mirror-error.js
+++ b/deps/v8/test/mjsunit/mirror-error.js
@@ -76,7 +76,7 @@ function testErrorMirror(e) {
}
assertTrue(found_message, 'Property message not found');
}
-
+
// Check the formatted text (regress 1231579).
assertEquals(fromJSON.text, e.toString(), 'toString');
}
diff --git a/deps/v8/test/mjsunit/regress/regress-1079.js b/deps/v8/test/mjsunit/regress/regress-1079.js
new file mode 100644
index 000000000..f3f3ce5ba
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-1079.js
@@ -0,0 +1,45 @@
+// Copyright 2011 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.
+
+// Getting the arguments property of an optimized function should not crash,
+// even if called through our optimized version of Function.prototype.apply.
+
+function optimized() {
+ return unoptimized.apply(null, arguments);
+}
+
+// It's not crucial that this is unoptimized.
+function unoptimized() {
+ with ({}) {
+ return optimized.arguments;
+ }
+}
+
+for (var i = 0; i < 100000; ++i) {
+ assertEquals(3, optimized(1, 2, 3).length);
+}
+
diff --git a/deps/v8/test/mjsunit/regress/regress-3408144.js b/deps/v8/test/mjsunit/regress/regress-3408144.js
new file mode 100644
index 000000000..6e292d635
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-3408144.js
@@ -0,0 +1,37 @@
+// Copyright 2011 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.
+
+// Test incorrect code generation for alternations on ARM.
+
+
+// Flags: --nofull-compiler
+
+function foo() {
+ return (0 > ("10"||10) - 1);
+}
+
+assertFalse(foo());
diff --git a/deps/v8/test/mjsunit/regress/regress-71647.js b/deps/v8/test/mjsunit/regress/regress-71647.js
new file mode 100644
index 000000000..44510116d
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-71647.js
@@ -0,0 +1,34 @@
+// Copyright 2011 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.
+
+var qe = 'object';
+
+function g() {
+ for (var i = 0; i < 10000; i++) typeof i === qe;
+}
+
+g();
diff --git a/deps/v8/test/mjsunit/strict-mode.js b/deps/v8/test/mjsunit/strict-mode.js
index 6f3a24413..3cb6d3292 100644
--- a/deps/v8/test/mjsunit/strict-mode.js
+++ b/deps/v8/test/mjsunit/strict-mode.js
@@ -62,17 +62,17 @@ function CheckFunctionConstructorStrictMode() {
}
// Incorrect 'use strict' directive.
-function UseStrictEscape() {
+(function UseStrictEscape() {
"use\\x20strict";
with ({}) {};
-}
+})();
// 'use strict' in non-directive position.
-function UseStrictNonDirective() {
+(function UseStrictNonDirective() {
void(0);
"use strict";
with ({}) {};
-}
+})();
// Multiple directives, including "use strict".
assertThrows('\
@@ -87,47 +87,47 @@ with({}) {}', SyntaxError);
CheckStrictMode("with({}) {}", SyntaxError);
// Function named 'eval'.
-CheckStrictMode("function eval() {}", SyntaxError)
+CheckStrictMode("function eval() {}", SyntaxError);
// Function named 'arguments'.
-CheckStrictMode("function arguments() {}", SyntaxError)
+CheckStrictMode("function arguments() {}", SyntaxError);
// Function parameter named 'eval'.
-CheckStrictMode("function foo(a, b, eval, c, d) {}", SyntaxError)
+CheckStrictMode("function foo(a, b, eval, c, d) {}", SyntaxError);
// Function parameter named 'arguments'.
-CheckStrictMode("function foo(a, b, arguments, c, d) {}", SyntaxError)
+CheckStrictMode("function foo(a, b, arguments, c, d) {}", SyntaxError);
// Property accessor parameter named 'eval'.
-CheckStrictMode("var o = { set foo(eval) {} }", SyntaxError)
+CheckStrictMode("var o = { set foo(eval) {} }", SyntaxError);
// Property accessor parameter named 'arguments'.
-CheckStrictMode("var o = { set foo(arguments) {} }", SyntaxError)
+CheckStrictMode("var o = { set foo(arguments) {} }", SyntaxError);
// Duplicate function parameter name.
-CheckStrictMode("function foo(a, b, c, d, b) {}", SyntaxError)
+CheckStrictMode("function foo(a, b, c, d, b) {}", SyntaxError);
// Function constructor: eval parameter name.
-CheckFunctionConstructorStrictMode("eval")
+CheckFunctionConstructorStrictMode("eval");
// Function constructor: arguments parameter name.
-CheckFunctionConstructorStrictMode("arguments")
+CheckFunctionConstructorStrictMode("arguments");
// Function constructor: duplicate parameter name.
-CheckFunctionConstructorStrictMode("a", "b", "c", "b")
-CheckFunctionConstructorStrictMode("a,b,c,b")
+CheckFunctionConstructorStrictMode("a", "b", "c", "b");
+CheckFunctionConstructorStrictMode("a,b,c,b");
// catch(eval)
-CheckStrictMode("try{}catch(eval){};", SyntaxError)
+CheckStrictMode("try{}catch(eval){};", SyntaxError);
// catch(arguments)
-CheckStrictMode("try{}catch(arguments){};", SyntaxError)
+CheckStrictMode("try{}catch(arguments){};", SyntaxError);
// var eval
-CheckStrictMode("var eval;", SyntaxError)
+CheckStrictMode("var eval;", SyntaxError);
// var arguments
-CheckStrictMode("var arguments;", SyntaxError)
+CheckStrictMode("var arguments;", SyntaxError);
// Strict mode applies to the function in which the directive is used..
assertThrows('\
@@ -136,12 +136,12 @@ function foo(eval) {\
}', SyntaxError);
// Strict mode doesn't affect the outer stop of strict code.
-function NotStrict(eval) {
+(function NotStrict(eval) {
function Strict() {
"use strict";
}
with ({}) {};
-}
+})();
// Octal literal
CheckStrictMode("var x = 012");
@@ -150,6 +150,12 @@ CheckStrictMode("'Hello octal\\032'");
CheckStrictMode("function octal() { return 012; }");
CheckStrictMode("function octal() { return '\\032'; }");
+(function ValidEscape() {
+ "use strict";
+ var x = '\0';
+ var y = "\0";
+})();
+
// Octal before "use strict"
assertThrows('\
function strict() {\
@@ -158,110 +164,110 @@ assertThrows('\
}', SyntaxError);
// Duplicate data properties.
-CheckStrictMode("var x = { dupe : 1, nondupe: 3, dupe : 2 };", SyntaxError)
-CheckStrictMode("var x = { '1234' : 1, '2345' : 2, '1234' : 3 };", SyntaxError)
-CheckStrictMode("var x = { '1234' : 1, '2345' : 2, 1234 : 3 };", SyntaxError)
-CheckStrictMode("var x = { 3.14 : 1, 2.71 : 2, 3.14 : 3 };", SyntaxError)
-CheckStrictMode("var x = { 3.14 : 1, '3.14' : 2 };", SyntaxError)
-CheckStrictMode("var x = { 123: 1, 123.00000000000000000000000000000000000000000000000000000000000000000001 : 2 }", SyntaxError)
+CheckStrictMode("var x = { dupe : 1, nondupe: 3, dupe : 2 };", SyntaxError);
+CheckStrictMode("var x = { '1234' : 1, '2345' : 2, '1234' : 3 };", SyntaxError);
+CheckStrictMode("var x = { '1234' : 1, '2345' : 2, 1234 : 3 };", SyntaxError);
+CheckStrictMode("var x = { 3.14 : 1, 2.71 : 2, 3.14 : 3 };", SyntaxError);
+CheckStrictMode("var x = { 3.14 : 1, '3.14' : 2 };", SyntaxError);
+CheckStrictMode("var x = { 123: 1, 123.00000000000000000000000000000000000000000000000000000000000000000001 : 2 }", SyntaxError);
// Non-conflicting data properties.
-function StrictModeNonDuplicate() {
+(function StrictModeNonDuplicate() {
"use strict";
var x = { 123 : 1, "0123" : 2 };
var x = { 123: 1, '123.00000000000000000000000000000000000000000000000000000000000000000001' : 2 }
-}
+})();
// Two getters (non-strict)
-assertThrows("var x = { get foo() { }, get foo() { } };", SyntaxError)
-assertThrows("var x = { get foo(){}, get 'foo'(){}};", SyntaxError)
-assertThrows("var x = { get 12(){}, get '12'(){}};", SyntaxError)
+assertThrows("var x = { get foo() { }, get foo() { } };", SyntaxError);
+assertThrows("var x = { get foo(){}, get 'foo'(){}};", SyntaxError);
+assertThrows("var x = { get 12(){}, get '12'(){}};", SyntaxError);
// Two setters (non-strict)
-assertThrows("var x = { set foo(v) { }, set foo(v) { } };", SyntaxError)
-assertThrows("var x = { set foo(v) { }, set 'foo'(v) { } };", SyntaxError)
-assertThrows("var x = { set 13(v) { }, set '13'(v) { } };", SyntaxError)
+assertThrows("var x = { set foo(v) { }, set foo(v) { } };", SyntaxError);
+assertThrows("var x = { set foo(v) { }, set 'foo'(v) { } };", SyntaxError);
+assertThrows("var x = { set 13(v) { }, set '13'(v) { } };", SyntaxError);
// Setter and data (non-strict)
-assertThrows("var x = { foo: 'data', set foo(v) { } };", SyntaxError)
-assertThrows("var x = { set foo(v) { }, foo: 'data' };", SyntaxError)
-assertThrows("var x = { foo: 'data', set 'foo'(v) { } };", SyntaxError)
-assertThrows("var x = { set foo(v) { }, 'foo': 'data' };", SyntaxError)
-assertThrows("var x = { 'foo': 'data', set foo(v) { } };", SyntaxError)
-assertThrows("var x = { set 'foo'(v) { }, foo: 'data' };", SyntaxError)
-assertThrows("var x = { 'foo': 'data', set 'foo'(v) { } };", SyntaxError)
-assertThrows("var x = { set 'foo'(v) { }, 'foo': 'data' };", SyntaxError)
+assertThrows("var x = { foo: 'data', set foo(v) { } };", SyntaxError);
+assertThrows("var x = { set foo(v) { }, foo: 'data' };", SyntaxError);
+assertThrows("var x = { foo: 'data', set 'foo'(v) { } };", SyntaxError);
+assertThrows("var x = { set foo(v) { }, 'foo': 'data' };", SyntaxError);
+assertThrows("var x = { 'foo': 'data', set foo(v) { } };", SyntaxError);
+assertThrows("var x = { set 'foo'(v) { }, foo: 'data' };", SyntaxError);
+assertThrows("var x = { 'foo': 'data', set 'foo'(v) { } };", SyntaxError);
+assertThrows("var x = { set 'foo'(v) { }, 'foo': 'data' };", SyntaxError);
assertThrows("var x = { 12: 1, set '12'(v){}};", SyntaxError);
assertThrows("var x = { 12: 1, set 12(v){}};", SyntaxError);
assertThrows("var x = { '12': 1, set '12'(v){}};", SyntaxError);
assertThrows("var x = { '12': 1, set 12(v){}};", SyntaxError);
// Getter and data (non-strict)
-assertThrows("var x = { foo: 'data', get foo() { } };", SyntaxError)
-assertThrows("var x = { get foo() { }, foo: 'data' };", SyntaxError)
-assertThrows("var x = { 'foo': 'data', get foo() { } };", SyntaxError)
-assertThrows("var x = { get 'foo'() { }, 'foo': 'data' };", SyntaxError)
+assertThrows("var x = { foo: 'data', get foo() { } };", SyntaxError);
+assertThrows("var x = { get foo() { }, foo: 'data' };", SyntaxError);
+assertThrows("var x = { 'foo': 'data', get foo() { } };", SyntaxError);
+assertThrows("var x = { get 'foo'() { }, 'foo': 'data' };", SyntaxError);
assertThrows("var x = { '12': 1, get '12'(){}};", SyntaxError);
assertThrows("var x = { '12': 1, get 12(){}};", SyntaxError);
// Assignment to eval or arguments
-CheckStrictMode("function strict() { eval = undefined; }", SyntaxError)
-CheckStrictMode("function strict() { arguments = undefined; }", SyntaxError)
-CheckStrictMode("function strict() { print(eval = undefined); }", SyntaxError)
-CheckStrictMode("function strict() { print(arguments = undefined); }", SyntaxError)
-CheckStrictMode("function strict() { var x = eval = undefined; }", SyntaxError)
-CheckStrictMode("function strict() { var x = arguments = undefined; }", SyntaxError)
+CheckStrictMode("function strict() { eval = undefined; }", SyntaxError);
+CheckStrictMode("function strict() { arguments = undefined; }", SyntaxError);
+CheckStrictMode("function strict() { print(eval = undefined); }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments = undefined); }", SyntaxError);
+CheckStrictMode("function strict() { var x = eval = undefined; }", SyntaxError);
+CheckStrictMode("function strict() { var x = arguments = undefined; }", SyntaxError);
// Compound assignment to eval or arguments
-CheckStrictMode("function strict() { eval *= undefined; }", SyntaxError)
-CheckStrictMode("function strict() { arguments /= undefined; }", SyntaxError)
-CheckStrictMode("function strict() { print(eval %= undefined); }", SyntaxError)
-CheckStrictMode("function strict() { print(arguments %= undefined); }", SyntaxError)
-CheckStrictMode("function strict() { var x = eval += undefined; }", SyntaxError)
-CheckStrictMode("function strict() { var x = arguments -= undefined; }", SyntaxError)
-CheckStrictMode("function strict() { eval <<= undefined; }", SyntaxError)
-CheckStrictMode("function strict() { arguments >>= undefined; }", SyntaxError)
-CheckStrictMode("function strict() { print(eval >>>= undefined); }", SyntaxError)
-CheckStrictMode("function strict() { print(arguments &= undefined); }", SyntaxError)
-CheckStrictMode("function strict() { var x = eval ^= undefined; }", SyntaxError)
-CheckStrictMode("function strict() { var x = arguments |= undefined; }", SyntaxError)
+CheckStrictMode("function strict() { eval *= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { arguments /= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { print(eval %= undefined); }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments %= undefined); }", SyntaxError);
+CheckStrictMode("function strict() { var x = eval += undefined; }", SyntaxError);
+CheckStrictMode("function strict() { var x = arguments -= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { eval <<= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { arguments >>= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { print(eval >>>= undefined); }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments &= undefined); }", SyntaxError);
+CheckStrictMode("function strict() { var x = eval ^= undefined; }", SyntaxError);
+CheckStrictMode("function strict() { var x = arguments |= undefined; }", SyntaxError);
// Postfix increment with eval or arguments
-CheckStrictMode("function strict() { eval++; }", SyntaxError)
-CheckStrictMode("function strict() { arguments++; }", SyntaxError)
-CheckStrictMode("function strict() { print(eval++); }", SyntaxError)
-CheckStrictMode("function strict() { print(arguments++); }", SyntaxError)
-CheckStrictMode("function strict() { var x = eval++; }", SyntaxError)
-CheckStrictMode("function strict() { var x = arguments++; }", SyntaxError)
+CheckStrictMode("function strict() { eval++; }", SyntaxError);
+CheckStrictMode("function strict() { arguments++; }", SyntaxError);
+CheckStrictMode("function strict() { print(eval++); }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments++); }", SyntaxError);
+CheckStrictMode("function strict() { var x = eval++; }", SyntaxError);
+CheckStrictMode("function strict() { var x = arguments++; }", SyntaxError);
// Postfix decrement with eval or arguments
-CheckStrictMode("function strict() { eval--; }", SyntaxError)
-CheckStrictMode("function strict() { arguments--; }", SyntaxError)
-CheckStrictMode("function strict() { print(eval--); }", SyntaxError)
-CheckStrictMode("function strict() { print(arguments--); }", SyntaxError)
-CheckStrictMode("function strict() { var x = eval--; }", SyntaxError)
-CheckStrictMode("function strict() { var x = arguments--; }", SyntaxError)
+CheckStrictMode("function strict() { eval--; }", SyntaxError);
+CheckStrictMode("function strict() { arguments--; }", SyntaxError);
+CheckStrictMode("function strict() { print(eval--); }", SyntaxError);
+CheckStrictMode("function strict() { print(arguments--); }", SyntaxError);
+CheckStrictMode("function strict() { var x = eval--; }", SyntaxError);
+CheckStrictMode("function strict() { var x = arguments--; }", SyntaxError);
// Prefix increment with eval or arguments
-CheckStrictMode("function strict() { ++eval; }", SyntaxError)
-CheckStrictMode("function strict() { ++arguments; }", SyntaxError)
-CheckStrictMode("function strict() { print(++eval); }", SyntaxError)
-CheckStrictMode("function strict() { print(++arguments); }", SyntaxError)
-CheckStrictMode("function strict() { var x = ++eval; }", SyntaxError)
-CheckStrictMode("function strict() { var x = ++arguments; }", SyntaxError)
+CheckStrictMode("function strict() { ++eval; }", SyntaxError);
+CheckStrictMode("function strict() { ++arguments; }", SyntaxError);
+CheckStrictMode("function strict() { print(++eval); }", SyntaxError);
+CheckStrictMode("function strict() { print(++arguments); }", SyntaxError);
+CheckStrictMode("function strict() { var x = ++eval; }", SyntaxError);
+CheckStrictMode("function strict() { var x = ++arguments; }", SyntaxError);
// Prefix decrement with eval or arguments
-CheckStrictMode("function strict() { --eval; }", SyntaxError)
-CheckStrictMode("function strict() { --arguments; }", SyntaxError)
-CheckStrictMode("function strict() { print(--eval); }", SyntaxError)
-CheckStrictMode("function strict() { print(--arguments); }", SyntaxError)
-CheckStrictMode("function strict() { var x = --eval; }", SyntaxError)
-CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError)
+CheckStrictMode("function strict() { --eval; }", SyntaxError);
+CheckStrictMode("function strict() { --arguments; }", SyntaxError);
+CheckStrictMode("function strict() { print(--eval); }", SyntaxError);
+CheckStrictMode("function strict() { print(--arguments); }", SyntaxError);
+CheckStrictMode("function strict() { var x = --eval; }", SyntaxError);
+CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError);
// Prefix unary operators other than delete, ++, -- are valid in strict mode
-function StrictModeUnaryOperators() {
+(function StrictModeUnaryOperators() {
"use strict";
var x = [void eval, typeof eval, +eval, -eval, ~eval, !eval];
var y = [void arguments, typeof arguments,
+arguments, -arguments, ~arguments, !arguments];
-} \ No newline at end of file
+})();
diff --git a/deps/v8/tools/v8.xcodeproj/project.pbxproj b/deps/v8/tools/v8.xcodeproj/project.pbxproj
index d02d2b1d5..86fcd8dca 100644
--- a/deps/v8/tools/v8.xcodeproj/project.pbxproj
+++ b/deps/v8/tools/v8.xcodeproj/project.pbxproj
@@ -47,6 +47,7 @@
890A14020EE9C4B400E49346 /* regexp-macro-assembler-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C750EE466D000B48DEB /* regexp-macro-assembler-irregexp.cc */; };
890A14030EE9C4B500E49346 /* regexp-macro-assembler-tracer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C770EE466D000B48DEB /* regexp-macro-assembler-tracer.cc */; };
890A14040EE9C4B700E49346 /* regexp-macro-assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C790EE466D000B48DEB /* regexp-macro-assembler.cc */; };
+ 8924315C12F8539900906AB2 /* lithium-gap-resolver-x64.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8924315A12F8539900906AB2 /* lithium-gap-resolver-x64.cc */; };
8938A2A312D63B630080CDDE /* lithium-x64.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8938A2A212D63B630080CDDE /* lithium-x64.cc */; };
893988070F2A35FA007D5254 /* libv8.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8970F2F00E719FB2006AE7B5 /* libv8.a */; };
8939880D0F2A362A007D5254 /* d8.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C920EE46A1700B48DEB /* d8.cc */; };
@@ -563,6 +564,8 @@
58950D5A0F55514900F3E8BA /* virtual-frame.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame.cc"; sourceTree = "<group>"; };
58950D5B0F55514900F3E8BA /* virtual-frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame.h"; sourceTree = "<group>"; };
8900116B0E71CA2300F91F35 /* libraries.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libraries.cc; sourceTree = "<group>"; };
+ 8924315A12F8539900906AB2 /* lithium-gap-resolver-x64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-gap-resolver-x64.cc"; path = "x64/lithium-gap-resolver-x64.cc"; sourceTree = "<group>"; };
+ 8924315B12F8539900906AB2 /* lithium-gap-resolver-x64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lithium-gap-resolver-x64.h"; path = "x64/lithium-gap-resolver-x64.h"; sourceTree = "<group>"; };
8938A2A212D63B630080CDDE /* lithium-x64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lithium-x64.cc"; path = "x64/lithium-x64.cc"; sourceTree = "<group>"; };
893986D40F29020C007D5254 /* apiutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apiutils.h; sourceTree = "<group>"; };
8939880B0F2A35FA007D5254 /* d8 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = d8; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1458,6 +1461,8 @@
89B91B8C12D4EF95002FF4BC /* jump-target-x64.cc */,
89F3605A12DCDF6400ACF8A6 /* lithium-codegen-x64.cc */,
89B91B8D12D4EF95002FF4BC /* lithium-codegen-x64.h */,
+ 8924315A12F8539900906AB2 /* lithium-gap-resolver-x64.cc */,
+ 8924315B12F8539900906AB2 /* lithium-gap-resolver-x64.h */,
8938A2A212D63B630080CDDE /* lithium-x64.cc */,
89B91B8E12D4EF95002FF4BC /* lithium-x64.h */,
89B91B8F12D4EF95002FF4BC /* macro-assembler-x64.cc */,
@@ -1979,6 +1984,7 @@
89F3605B12DCDF6400ACF8A6 /* lithium-codegen-x64.cc in Sources */,
89D7DDDE12E8DE09001E2B82 /* gdb-jit.cc in Sources */,
89D7DDDF12E8DE09001E2B82 /* inspector.cc in Sources */,
+ 8924315C12F8539900906AB2 /* lithium-gap-resolver-x64.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};