Version 3.9.13
Add code kind check before preparing for OSR. (issue 1900, 115073)
Pass zone explicitly to zone-allocation on x64 and ARM. (issue 1802)
Port string construct stub to x64. (issue 849)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@10875 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 5b852bb..e5fd5ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-02-29: Version 3.9.13
+
+ Add code kind check before preparing for OSR. (issue 1900, 115073)
+
+ Pass zone explicitly to zone-allocation on x64 and ARM. (issue 1802)
+
+ Port string construct stub to x64. (issue 849)
+
+ Performance and stability improvements on all platforms.
+
+
2012-02-28: Version 3.9.12
Fix the negative lookup stub to handle deleted entries in a dictionary.
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 14daada..e843657 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -399,7 +399,7 @@
NORMAL,
argc);
Isolate::Current()->stub_cache()->GenerateProbe(
- masm, flags, r1, r2, r3, r4, r5);
+ masm, flags, r1, r2, r3, r4, r5, r6);
// If the stub cache probing failed, the receiver might be a value.
// For value objects, we use the map of the prototype objects for
@@ -438,7 +438,7 @@
// Probe the stub cache for the value object.
__ bind(&probe);
Isolate::Current()->stub_cache()->GenerateProbe(
- masm, flags, r1, r2, r3, r4, r5);
+ masm, flags, r1, r2, r3, r4, r5, r6);
__ bind(&miss);
}
@@ -706,7 +706,7 @@
Code::Flags flags =
Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
Isolate::Current()->stub_cache()->GenerateProbe(
- masm, flags, r0, r2, r3, r4, r5);
+ masm, flags, r0, r2, r3, r4, r5, r6);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
@@ -1516,7 +1516,7 @@
Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC, strict_mode);
Isolate::Current()->stub_cache()->GenerateProbe(
- masm, flags, r1, r2, r3, r4, r5);
+ masm, flags, r1, r2, r3, r4, r5, r6);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 4e20404..26cfcbd 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -476,7 +476,7 @@
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
- LInstructionGap* gap = new LInstructionGap(block);
+ LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
int index = -1;
if (instr->IsControl()) {
instructions_.Add(gap);
@@ -551,7 +551,7 @@
LChunk* LChunkBuilder::Build() {
ASSERT(is_unused());
- chunk_ = new LChunk(info(), graph());
+ chunk_ = new(zone()) LChunk(info(), graph());
HPhase phase("Building chunk", chunk_);
status_ = BUILDING;
const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
@@ -582,14 +582,14 @@
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new LUnallocated(LUnallocated::FIXED_REGISTER,
- Register::ToAllocationIndex(reg));
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
- return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
- DoubleRegister::ToAllocationIndex(reg));
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg));
}
@@ -604,30 +604,30 @@
LOperand* LChunkBuilder::UseRegister(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
}
LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
return Use(value,
- new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
- LUnallocated::USED_AT_START));
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
+ LUnallocated::USED_AT_START));
}
LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
}
LOperand* LChunkBuilder::Use(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::NONE));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
}
LOperand* LChunkBuilder::UseAtStart(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::NONE,
- LUnallocated::USED_AT_START));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
+ LUnallocated::USED_AT_START));
}
@@ -662,7 +662,7 @@
LOperand* LChunkBuilder::UseAny(HValue* value) {
return value->IsConstant()
? chunk_->DefineConstantOperand(HConstant::cast(value))
- : Use(value, new LUnallocated(LUnallocated::ANY));
+ : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
}
@@ -688,21 +688,24 @@
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsRegister(
LTemplateInstruction<1, I, T>* instr) {
- return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
}
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsSpilled(
LTemplateInstruction<1, I, T>* instr, int index) {
- return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
}
template<int I, int T>
LInstruction* LChunkBuilder::DefineSameAsFirst(
LTemplateInstruction<1, I, T>* instr) {
- return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
}
@@ -784,13 +787,14 @@
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
ASSERT(!instr->HasPointerMap());
- instr->set_pointer_map(new LPointerMap(position_));
+ instr->set_pointer_map(new(zone()) LPointerMap(position_));
return instr;
}
LUnallocated* LChunkBuilder::TempRegister() {
- LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
+ LUnallocated* operand =
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
return operand;
@@ -812,17 +816,17 @@
LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
- return new LLabel(instr->block());
+ return new(zone()) LLabel(instr->block());
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
- return AssignEnvironment(new LDeoptimize);
+ return AssignEnvironment(new(zone()) LDeoptimize);
}
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
- return AssignEnvironment(new LDeoptimize);
+ return AssignEnvironment(new(zone()) LDeoptimize);
}
@@ -834,7 +838,7 @@
LOperand* left = UseFixed(instr->left(), r1);
LOperand* right = UseFixed(instr->right(), r0);
- LArithmeticT* result = new LArithmeticT(op, left, right);
+ LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -868,7 +872,7 @@
}
LInstruction* result =
- DefineAsRegister(new LShiftI(op, left, right, does_deopt));
+ DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
return does_deopt ? AssignEnvironment(result) : result;
}
@@ -881,7 +885,7 @@
ASSERT(op != Token::MOD);
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- LArithmeticD* result = new LArithmeticD(op, left, right);
+ LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
return DefineAsRegister(result);
}
@@ -899,7 +903,8 @@
ASSERT(right->representation().IsTagged());
LOperand* left_operand = UseFixed(left, r1);
LOperand* right_operand = UseFixed(right, r0);
- LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
+ LArithmeticT* result =
+ new(zone()) LArithmeticT(op, left_operand, right_operand);
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -998,13 +1003,14 @@
ASSERT(ast_id != AstNode::kNoNumber ||
hydrogen_env->frame_type() != JS_FUNCTION);
int value_count = hydrogen_env->length();
- LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
- hydrogen_env->frame_type(),
- ast_id,
- hydrogen_env->parameter_count(),
- argument_count_,
- value_count,
- outer);
+ LEnvironment* result = new(zone()) LEnvironment(
+ hydrogen_env->closure(),
+ hydrogen_env->frame_type(),
+ ast_id,
+ hydrogen_env->parameter_count(),
+ argument_count_,
+ value_count,
+ outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue;
@@ -1014,7 +1020,7 @@
if (value->IsArgumentsObject()) {
op = NULL;
} else if (value->IsPushArgument()) {
- op = new LArgument(argument_index++);
+ op = new(zone()) LArgument(argument_index++);
} else {
op = UseAny(value);
}
@@ -1030,7 +1036,7 @@
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
- return new LGoto(instr->FirstSuccessor()->block_id());
+ return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
}
@@ -1040,10 +1046,10 @@
HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
- return new LGoto(successor->block_id());
+ return new(zone()) LGoto(successor->block_id());
}
- LBranch* result = new LBranch(UseRegister(value));
+ LBranch* result = new(zone()) LBranch(UseRegister(value));
// Tagged values that are not known smis or booleans require a
// deoptimization environment.
Representation rep = value->representation();
@@ -1060,23 +1066,24 @@
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister();
- return new LCmpMapAndBranch(value, temp);
+ return new(zone()) LCmpMapAndBranch(value, temp);
}
-LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
- return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
+LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
+ LOperand* value = UseRegister(instr->value());
+ return DefineAsRegister(new(zone()) LArgumentsLength(value));
}
LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
- return DefineAsRegister(new LArgumentsElements);
+ return DefineAsRegister(new(zone()) LArgumentsElements);
}
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LInstanceOf* result =
- new LInstanceOf(UseFixed(instr->left(), r0),
+ new(zone()) LInstanceOf(UseFixed(instr->left(), r0),
UseFixed(instr->right(), r1));
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1085,7 +1092,8 @@
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
HInstanceOfKnownGlobal* instr) {
LInstanceOfKnownGlobal* result =
- new LInstanceOfKnownGlobal(UseFixed(instr->left(), r0), FixedTemp(r4));
+ new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r0),
+ FixedTemp(r4));
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1095,7 +1103,7 @@
LOperand* receiver = UseFixed(instr->receiver(), r0);
LOperand* length = UseFixed(instr->length(), r2);
LOperand* elements = UseFixed(instr->elements(), r3);
- LApplyArguments* result = new LApplyArguments(function,
+ LApplyArguments* result = new(zone()) LApplyArguments(function,
receiver,
length,
elements);
@@ -1106,54 +1114,56 @@
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
++argument_count_;
LOperand* argument = Use(instr->argument());
- return new LPushArgument(argument);
+ return new(zone()) LPushArgument(argument);
}
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
+ return instr->HasNoUses()
+ ? NULL
+ : DefineAsRegister(new(zone()) LThisFunction);
}
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
+ return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
}
LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LOuterContext(context));
+ return DefineAsRegister(new(zone()) LOuterContext(context));
}
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
- return MarkAsCall(new LDeclareGlobals, instr);
+ return MarkAsCall(new(zone()) LDeclareGlobals, instr);
}
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGlobalObject(context));
+ return DefineAsRegister(new(zone()) LGlobalObject(context));
}
LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
LOperand* global_object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGlobalReceiver(global_object));
+ return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
}
LInstruction* LChunkBuilder::DoCallConstantFunction(
HCallConstantFunction* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, r0), instr);
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* function = UseFixed(instr->function(), r1);
argument_count_ -= instr->argument_count();
- LInvokeFunction* result = new LInvokeFunction(function);
+ LInvokeFunction* result = new(zone()) LInvokeFunction(function);
return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
@@ -1162,17 +1172,17 @@
BuiltinFunctionId op = instr->op();
if (op == kMathLog || op == kMathSin || op == kMathCos) {
LOperand* input = UseFixedDouble(instr->value(), d2);
- LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL);
return MarkAsCall(DefineFixedDouble(result, d2), instr);
} else if (op == kMathPowHalf) {
LOperand* input = UseFixedDouble(instr->value(), d2);
LOperand* temp = FixedTemp(d3);
- LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
return DefineFixedDouble(result, d2);
} else {
LOperand* input = UseRegisterAtStart(instr->value());
LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
- LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
switch (op) {
case kMathAbs:
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
@@ -1194,32 +1204,32 @@
ASSERT(instr->key()->representation().IsTagged());
argument_count_ -= instr->argument_count();
LOperand* key = UseFixed(instr->key(), r2);
- return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r0), instr);
}
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r0), instr);
}
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr);
}
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, r0), instr);
}
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
LOperand* constructor = UseFixed(instr->constructor(), r1);
argument_count_ -= instr->argument_count();
- LCallNew* result = new LCallNew(constructor);
+ LCallNew* result = new(zone()) LCallNew(constructor);
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1227,13 +1237,14 @@
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
LOperand* function = UseFixed(instr->function(), r1);
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallFunction(function), r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r0),
+ instr);
}
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r0), instr);
}
@@ -1259,7 +1270,7 @@
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- return DefineAsRegister(new LBitI(left, right));
+ return DefineAsRegister(new(zone()) LBitI(left, right));
} else {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged());
@@ -1267,7 +1278,7 @@
LOperand* left = UseFixed(instr->left(), r1);
LOperand* right = UseFixed(instr->right(), r0);
- LArithmeticT* result = new LArithmeticT(instr->op(), left, right);
+ LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
return MarkAsCall(DefineFixed(result, r0), instr);
}
}
@@ -1276,7 +1287,8 @@
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ASSERT(instr->value()->representation().IsInteger32());
ASSERT(instr->representation().IsInteger32());
- return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value())));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new(zone()) LBitNotI(value));
}
@@ -1292,7 +1304,7 @@
LOperand* dividend = UseFixed(instr->left(), r0);
LOperand* divisor = UseFixed(instr->right(), r1);
return AssignEnvironment(AssignPointerMap(
- DefineFixed(new LDivI(dividend, divisor), r0)));
+ DefineFixed(new(zone()) LDivI(dividend, divisor), r0)));
} else {
return DoArithmeticT(Token::DIV, instr);
}
@@ -1308,15 +1320,15 @@
if (instr->HasPowerOf2Divisor()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
- mod = new LModI(value, UseOrConstant(instr->right()));
+ mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
} else {
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = UseRegister(instr->right());
- mod = new LModI(dividend,
- divisor,
- TempRegister(),
- FixedTemp(d10),
- FixedTemp(d11));
+ mod = new(zone()) LModI(dividend,
+ divisor,
+ TempRegister(),
+ FixedTemp(d10),
+ FixedTemp(d11));
}
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
@@ -1334,7 +1346,7 @@
// TODO(fschneider): Allow any register as input registers.
LOperand* left = UseFixedDouble(instr->left(), d1);
LOperand* right = UseFixedDouble(instr->right(), d2);
- LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
+ LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
return MarkAsCall(DefineFixedDouble(result, d1), instr);
}
}
@@ -1355,7 +1367,7 @@
} else {
left = UseRegisterAtStart(instr->LeastConstantOperand());
}
- LMulI* mul = new LMulI(left, right, temp);
+ LMulI* mul = new(zone()) LMulI(left, right, temp);
if (instr->CheckFlag(HValue::kCanOverflow) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
AssignEnvironment(mul);
@@ -1377,7 +1389,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
- LSubI* sub = new LSubI(left, right);
+ LSubI* sub = new(zone()) LSubI(left, right);
LInstruction* result = DefineAsRegister(sub);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
@@ -1397,7 +1409,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- LAddI* add = new LAddI(left, right);
+ LAddI* add = new(zone()) LAddI(left, right);
LInstruction* result = DefineAsRegister(add);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
@@ -1422,7 +1434,7 @@
LOperand* right = exponent_type.IsDouble() ?
UseFixedDouble(instr->right(), d2) :
UseFixed(instr->right(), r2);
- LPower* result = new LPower(left, right);
+ LPower* result = new(zone()) LPower(left, right);
return MarkAsCall(DefineFixedDouble(result, d3),
instr,
CAN_DEOPTIMIZE_EAGERLY);
@@ -1433,7 +1445,7 @@
ASSERT(instr->representation().IsDouble());
ASSERT(instr->global_object()->representation().IsTagged());
LOperand* global_object = UseFixed(instr->global_object(), r0);
- LRandom* result = new LRandom(global_object);
+ LRandom* result = new(zone()) LRandom(global_object);
return MarkAsCall(DefineFixedDouble(result, d7), instr);
}
@@ -1443,7 +1455,7 @@
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), r1);
LOperand* right = UseFixed(instr->right(), r0);
- LCmpT* result = new LCmpT(left, right);
+ LCmpT* result = new(zone()) LCmpT(left, right);
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1456,14 +1468,14 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
- return new LCmpIDAndBranch(left, right);
+ return new(zone()) LCmpIDAndBranch(left, right);
} else {
ASSERT(r.IsDouble());
ASSERT(instr->left()->representation().IsDouble());
ASSERT(instr->right()->representation().IsDouble());
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return new LCmpIDAndBranch(left, right);
+ return new(zone()) LCmpIDAndBranch(left, right);
}
}
@@ -1472,47 +1484,50 @@
HCompareObjectEqAndBranch* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return new LCmpObjectEqAndBranch(left, right);
+ return new(zone()) LCmpObjectEqAndBranch(left, right);
}
LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
HCompareConstantEqAndBranch* instr) {
- return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value()));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LCmpConstantEqAndBranch(value);
}
LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsNilAndBranch(UseRegisterAtStart(instr->value()));
+ return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
}
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
+ LOperand* value = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister();
- return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()), temp);
+ return new(zone()) LIsObjectAndBranch(value, temp);
}
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
+ LOperand* value = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister();
- return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp);
+ return new(zone()) LIsStringAndBranch(value, temp);
}
LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsSmiAndBranch(Use(instr->value()));
+ return new(zone()) LIsSmiAndBranch(Use(instr->value()));
}
LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
HIsUndetectableAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()),
- TempRegister());
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
}
@@ -1522,7 +1537,8 @@
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), r1);
LOperand* right = UseFixed(instr->right(), r0);
- LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right);
+ LStringCompareAndBranch* result =
+ new(zone()) LStringCompareAndBranch(left, right);
return MarkAsCall(result, instr);
}
@@ -1530,7 +1546,8 @@
LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
HHasInstanceTypeAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value()));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LHasInstanceTypeAndBranch(value);
}
@@ -1539,14 +1556,14 @@
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGetCachedArrayIndex(value));
+ return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
}
LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
HHasCachedArrayIndexAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LHasCachedArrayIndexAndBranch(
+ return new(zone()) LHasCachedArrayIndexAndBranch(
UseRegisterAtStart(instr->value()));
}
@@ -1554,40 +1571,41 @@
LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
HClassOfTestAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LClassOfTestAndBranch(UseRegister(instr->value()),
- TempRegister());
+ LOperand* value = UseRegister(instr->value());
+ return new(zone()) LClassOfTestAndBranch(value, TempRegister());
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LJSArrayLength(array));
+ return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LFixedArrayBaseLength(array));
+ return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
}
LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
LOperand* object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LElementsKind(object));
+ return DefineAsRegister(new(zone()) LElementsKind(object));
}
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value());
- LValueOf* result = new LValueOf(object, TempRegister());
+ LValueOf* result = new(zone()) LValueOf(object, TempRegister());
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
- UseRegister(instr->length())));
+ LOperand* value = UseRegisterAtStart(instr->index());
+ LOperand* length = UseRegister(instr->length());
+ return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
}
@@ -1600,7 +1618,7 @@
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
LOperand* value = UseFixed(instr->value(), r0);
- return MarkAsCall(new LThrow(value), instr);
+ return MarkAsCall(new(zone()) LThrow(value), instr);
}
@@ -1623,7 +1641,7 @@
if (from.IsTagged()) {
if (to.IsDouble()) {
LOperand* value = UseRegister(instr->value());
- LNumberUntagD* res = new LNumberUntagD(value);
+ LNumberUntagD* res = new(zone()) LNumberUntagD(value);
return AssignEnvironment(DefineAsRegister(res));
} else {
ASSERT(to.IsInteger32());
@@ -1631,14 +1649,17 @@
bool needs_check = !instr->value()->type().IsSmi();
LInstruction* res = NULL;
if (!needs_check) {
- res = DefineAsRegister(new LSmiUntag(value, needs_check));
+ res = DefineAsRegister(new(zone()) LSmiUntag(value, needs_check));
} else {
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
: NULL;
- res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
+ res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
+ temp1,
+ temp2,
+ temp3));
res = AssignEnvironment(res);
}
return res;
@@ -1652,16 +1673,15 @@
// Make sure that the temp and result_temp registers are
// different.
LUnallocated* result_temp = TempRegister();
- LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
+ LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
Define(result, result_temp);
return AssignPointerMap(result);
} else {
ASSERT(to.IsInteger32());
LOperand* value = UseRegister(instr->value());
- LDoubleToI* res =
- new LDoubleToI(value,
- TempRegister(),
- instr->CanTruncateToInt32() ? TempRegister() : NULL);
+ LOperand* temp1 = TempRegister();
+ LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
+ LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
return AssignEnvironment(DefineAsRegister(res));
}
} else if (from.IsInteger32()) {
@@ -1669,15 +1689,15 @@
HValue* val = instr->value();
LOperand* value = UseRegisterAtStart(val);
if (val->HasRange() && val->range()->IsInSmiRange()) {
- return DefineAsRegister(new LSmiTag(value));
+ return DefineAsRegister(new(zone()) LSmiTag(value));
} else {
- LNumberTagI* result = new LNumberTagI(value);
+ LNumberTagI* result = new(zone()) LNumberTagI(value);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
}
} else {
ASSERT(to.IsDouble());
LOperand* value = Use(instr->value());
- return DefineAsRegister(new LInteger32ToDouble(value));
+ return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
}
}
UNREACHABLE();
@@ -1687,13 +1707,13 @@
LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckNonSmi(value));
+ return AssignEnvironment(new(zone()) LCheckNonSmi(value));
}
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- LInstruction* result = new LCheckInstanceType(value);
+ LInstruction* result = new(zone()) LCheckInstanceType(value);
return AssignEnvironment(result);
}
@@ -1701,26 +1721,26 @@
LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
- LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
+ LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
return AssignEnvironment(result);
}
LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckSmi(value));
+ return AssignEnvironment(new(zone()) LCheckSmi(value));
}
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckFunction(value));
+ return AssignEnvironment(new(zone()) LCheckFunction(value));
}
LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- LInstruction* result = new LCheckMap(value);
+ LInstruction* result = new(zone()) LCheckMap(value);
return AssignEnvironment(result);
}
@@ -1730,14 +1750,14 @@
Representation input_rep = value->representation();
LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) {
- return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11)));
+ return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11)));
} else if (input_rep.IsInteger32()) {
- return DefineAsRegister(new LClampIToUint8(reg));
+ return DefineAsRegister(new(zone()) LClampIToUint8(reg));
} else {
ASSERT(input_rep.IsTagged());
// Register allocator doesn't (yet) support allocation of double
// temps. Reserve d1 explicitly.
- LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11));
+ LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11));
return AssignEnvironment(DefineAsRegister(result));
}
}
@@ -1750,7 +1770,7 @@
if (input_rep.IsDouble()) {
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
- LDoubleToI* res = new LDoubleToI(reg, temp1, temp2);
+ LDoubleToI* res = new(zone()) LDoubleToI(reg, temp1, temp2);
return AssignEnvironment(DefineAsRegister(res));
} else if (input_rep.IsInteger32()) {
// Canonicalization should already have removed the hydrogen instruction in
@@ -1762,25 +1782,25 @@
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LOperand* temp3 = FixedTemp(d11);
- LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
+ LTaggedToI* res = new(zone()) LTaggedToI(reg, temp1, temp2, temp3);
return AssignEnvironment(DefineSameAsFirst(res));
}
}
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
- return new LReturn(UseFixed(instr->value(), r0));
+ return new(zone()) LReturn(UseFixed(instr->value(), r0));
}
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
Representation r = instr->representation();
if (r.IsInteger32()) {
- return DefineAsRegister(new LConstantI);
+ return DefineAsRegister(new(zone()) LConstantI);
} else if (r.IsDouble()) {
- return DefineAsRegister(new LConstantD);
+ return DefineAsRegister(new(zone()) LConstantD);
} else if (r.IsTagged()) {
- return DefineAsRegister(new LConstantT);
+ return DefineAsRegister(new(zone()) LConstantT);
} else {
UNREACHABLE();
return NULL;
@@ -1789,7 +1809,7 @@
LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
- LLoadGlobalCell* result = new LLoadGlobalCell;
+ LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
return instr->RequiresHoleCheck()
? AssignEnvironment(DefineAsRegister(result))
: DefineAsRegister(result);
@@ -1798,7 +1818,7 @@
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* global_object = UseFixed(instr->global_object(), r0);
- LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
+ LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -1808,8 +1828,8 @@
// Use a temp to check the value in the cell in the case where we perform
// a hole check.
return instr->RequiresHoleCheck()
- ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister()))
- : new LStoreGlobalCell(value, NULL);
+ ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
+ : new(zone()) LStoreGlobalCell(value, NULL);
}
@@ -1817,14 +1837,15 @@
LOperand* global_object = UseFixed(instr->global_object(), r1);
LOperand* value = UseFixed(instr->value(), r0);
LStoreGlobalGeneric* result =
- new LStoreGlobalGeneric(global_object, value);
+ new(zone()) LStoreGlobalGeneric(global_object, value);
return MarkAsCall(result, instr);
}
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- LInstruction* result = DefineAsRegister(new LLoadContextSlot(context));
+ LInstruction* result =
+ DefineAsRegister(new(zone()) LLoadContextSlot(context));
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
}
@@ -1839,14 +1860,14 @@
context = UseRegister(instr->context());
value = UseRegister(instr->value());
}
- LInstruction* result = new LStoreContextSlot(context, value);
+ LInstruction* result = new(zone()) LStoreContextSlot(context, value);
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
}
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
return DefineAsRegister(
- new LLoadNamedField(UseRegisterAtStart(instr->object())));
+ new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
}
@@ -1855,11 +1876,13 @@
ASSERT(instr->representation().IsTagged());
if (instr->need_generic()) {
LOperand* obj = UseFixed(instr->object(), r0);
- LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
return MarkAsCall(DefineFixed(result, r0), instr);
} else {
LOperand* obj = UseRegisterAtStart(instr->object());
- LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
return AssignEnvironment(DefineAsRegister(result));
}
}
@@ -1867,7 +1890,7 @@
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), r0);
- LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
+ LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0);
return MarkAsCall(result, instr);
}
@@ -1875,20 +1898,20 @@
LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
HLoadFunctionPrototype* instr) {
return AssignEnvironment(DefineAsRegister(
- new LLoadFunctionPrototype(UseRegister(instr->function()))));
+ new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
}
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadElements(input));
+ return DefineAsRegister(new(zone()) LLoadElements(input));
}
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
HLoadExternalArrayPointer* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadExternalArrayPointer(input));
+ return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
}
@@ -1898,7 +1921,7 @@
ASSERT(instr->key()->representation().IsInteger32());
LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterAtStart(instr->key());
- LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
+ LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
if (instr->RequiresHoleCheck()) AssignEnvironment(result);
return DefineAsRegister(result);
}
@@ -1911,7 +1934,7 @@
LOperand* elements = UseTempRegister(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
- new LLoadKeyedFastDoubleElement(elements, key);
+ new(zone()) LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
@@ -1930,7 +1953,7 @@
LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key());
LLoadKeyedSpecializedArrayElement* result =
- new LLoadKeyedSpecializedArrayElement(external_pointer, key);
+ new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
@@ -1944,7 +1967,7 @@
LOperand* key = UseFixed(instr->key(), r0);
LInstruction* result =
- DefineFixed(new LLoadKeyedGeneric(object, key), r0);
+ DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0);
return MarkAsCall(result, instr);
}
@@ -1963,7 +1986,7 @@
LOperand* key = needs_write_barrier
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
- return new LStoreKeyedFastElement(obj, key, val);
+ return new(zone()) LStoreKeyedFastElement(obj, key, val);
}
@@ -1977,7 +2000,7 @@
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- return new LStoreKeyedFastDoubleElement(elements, key, val);
+ return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
}
@@ -2003,9 +2026,9 @@
: UseRegister(instr->value());
LOperand* key = UseRegisterOrConstant(instr->key());
- return new LStoreKeyedSpecializedArrayElement(external_pointer,
- key,
- val);
+ return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
+ key,
+ val);
}
@@ -2018,7 +2041,7 @@
ASSERT(instr->key()->representation().IsTagged());
ASSERT(instr->value()->representation().IsTagged());
- return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
+ return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
}
@@ -2029,14 +2052,16 @@
LOperand* object = UseRegister(instr->object());
LOperand* new_map_reg = TempRegister();
LTransitionElementsKind* result =
- new LTransitionElementsKind(object, new_map_reg, NULL);
+ new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
return DefineSameAsFirst(result);
} else {
LOperand* object = UseFixed(instr->object(), r0);
LOperand* fixed_object_reg = FixedTemp(r2);
LOperand* new_map_reg = FixedTemp(r3);
LTransitionElementsKind* result =
- new LTransitionElementsKind(object, new_map_reg, fixed_object_reg);
+ new(zone()) LTransitionElementsKind(object,
+ new_map_reg,
+ fixed_object_reg);
return MarkAsCall(DefineFixed(result, r0), instr);
}
}
@@ -2053,7 +2078,7 @@
? UseTempRegister(instr->value())
: UseRegister(instr->value());
- return new LStoreNamedField(obj, val);
+ return new(zone()) LStoreNamedField(obj, val);
}
@@ -2061,7 +2086,7 @@
LOperand* obj = UseFixed(instr->object(), r1);
LOperand* val = UseFixed(instr->value(), r0);
- LInstruction* result = new LStoreNamedGeneric(obj, val);
+ LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
return MarkAsCall(result, instr);
}
@@ -2069,28 +2094,29 @@
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return MarkAsCall(DefineFixed(new LStringAdd(left, right), r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r0),
+ instr);
}
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
LOperand* string = UseTempRegister(instr->string());
LOperand* index = UseTempRegister(instr->index());
- LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
+ LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
}
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
LOperand* char_code = UseRegister(instr->value());
- LStringCharFromCode* result = new LStringCharFromCode(char_code);
+ LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
return AssignPointerMap(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LStringLength(string));
+ return DefineAsRegister(new(zone()) LStringLength(string));
}
@@ -2101,34 +2127,34 @@
LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
- return MarkAsCall(DefineFixed(new LFastLiteral, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, r0), instr);
}
LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
- return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, r0), instr);
}
LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
- return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, r0), instr);
}
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
- return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr);
}
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
- return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr);
}
LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
LOperand* object = UseFixed(instr->object(), r0);
LOperand* key = UseFixed(instr->key(), r1);
- LDeleteProperty* result = new LDeleteProperty(object, key);
+ LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
return MarkAsCall(DefineFixed(result, r0), instr);
}
@@ -2136,13 +2162,13 @@
LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
allocator_->MarkAsOsrEntry();
current_block_->last_environment()->set_ast_id(instr->ast_id());
- return AssignEnvironment(new LOsrEntry);
+ return AssignEnvironment(new(zone()) LOsrEntry);
}
LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
int spill_index = chunk()->GetParameterStackSlot(instr->index());
- return DefineAsSpilled(new LParameter, spill_index);
+ return DefineAsSpilled(new(zone()) LParameter, spill_index);
}
@@ -2152,13 +2178,13 @@
Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
- return DefineAsSpilled(new LUnknownOSRValue, spill_index);
+ return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
}
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallStub, r0), instr);
}
@@ -2175,32 +2201,33 @@
LOperand* arguments = UseRegister(instr->arguments());
LOperand* length = UseTempRegister(instr->length());
LOperand* index = UseRegister(instr->index());
- LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
+ LAccessArgumentsAt* result =
+ new(zone()) LAccessArgumentsAt(arguments, length, index);
return AssignEnvironment(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
LOperand* object = UseFixed(instr->value(), r0);
- LToFastProperties* result = new LToFastProperties(object);
+ LToFastProperties* result = new(zone()) LToFastProperties(object);
return MarkAsCall(DefineFixed(result, r0), instr);
}
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
- LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
+ LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r0));
return MarkAsCall(DefineFixed(result, r0), instr);
}
LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
- return new LTypeofIsAndBranch(UseTempRegister(instr->value()));
+ return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
}
LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
HIsConstructCallAndBranch* instr) {
- return new LIsConstructCallAndBranch(TempRegister());
+ return new(zone()) LIsConstructCallAndBranch(TempRegister());
}
@@ -2223,7 +2250,7 @@
// 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()) {
- LInstruction* result = new LLazyBailout;
+ LInstruction* result = new(zone()) LLazyBailout;
result = AssignEnvironment(result);
instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
@@ -2237,10 +2264,10 @@
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
if (instr->is_function_entry()) {
- return MarkAsCall(new LStackCheck, instr);
+ return MarkAsCall(new(zone()) LStackCheck, instr);
} else {
ASSERT(instr->is_backwards_branch());
- return AssignEnvironment(AssignPointerMap(new LStackCheck));
+ return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
}
}
@@ -2271,14 +2298,14 @@
LInstruction* LChunkBuilder::DoIn(HIn* instr) {
LOperand* key = UseRegisterAtStart(instr->key());
LOperand* object = UseRegisterAtStart(instr->object());
- LIn* result = new LIn(key, object);
+ LIn* result = new(zone()) LIn(key, object);
return MarkAsCall(DefineFixed(result, r0), instr);
}
LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
LOperand* object = UseFixed(instr->enumerable(), r0);
- LForInPrepareMap* result = new LForInPrepareMap(object);
+ LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
}
@@ -2286,21 +2313,21 @@
LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
LOperand* map = UseRegister(instr->map());
return AssignEnvironment(DefineAsRegister(
- new LForInCacheArray(map)));
+ new(zone()) LForInCacheArray(map)));
}
LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
LOperand* map = UseRegisterAtStart(instr->map());
- return AssignEnvironment(new LCheckMapValue(value, map));
+ return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
}
LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
LOperand* object = UseRegister(instr->object());
LOperand* index = UseRegister(instr->index());
- return DefineAsRegister(new LLoadFieldByIndex(object, index));
+ return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
}
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 81566c4..ba7c35d 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -2200,6 +2200,7 @@
: chunk_(NULL),
info_(info),
graph_(graph),
+ zone_(graph->isolate()->zone()),
status_(UNUSED),
current_instruction_(NULL),
current_block_(NULL),
@@ -2229,6 +2230,7 @@
LChunk* chunk() const { return chunk_; }
CompilationInfo* info() const { return info_; }
HGraph* graph() const { return graph_; }
+ Zone* zone() const { return zone_; }
bool is_unused() const { return status_ == UNUSED; }
bool is_building() const { return status_ == BUILDING; }
@@ -2333,6 +2335,7 @@
LChunk* chunk_;
CompilationInfo* info_;
HGraph* const graph_;
+ Zone* zone_;
Status status_;
HInstruction* current_instruction_;
HBasicBlock* current_block_;
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 880c372..de83c13 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -1055,7 +1055,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt();
+ MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 9a0793e..74fca2e 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -43,59 +43,83 @@
MacroAssembler* masm,
Code::Flags flags,
StubCache::Table table,
+ Register receiver,
Register name,
+ // Number of the cache entry, not scaled.
Register offset,
- int offset_shift_bits,
Register scratch,
- Register scratch2) {
+ Register scratch2,
+ Register offset_scratch) {
ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
+ ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
+ uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address());
// Check the relative positions of the address fields.
ASSERT(value_off_addr > key_off_addr);
ASSERT((value_off_addr - key_off_addr) % 4 == 0);
ASSERT((value_off_addr - key_off_addr) < (256 * 4));
+ ASSERT(map_off_addr > key_off_addr);
+ ASSERT((map_off_addr - key_off_addr) % 4 == 0);
+ ASSERT((map_off_addr - key_off_addr) < (256 * 4));
Label miss;
- Register offsets_base_addr = scratch;
+ Register base_addr = scratch;
+ scratch = no_reg;
+
+ // Multiply by 3 because there are 3 fields per entry (name, code, map).
+ __ add(offset_scratch, offset, Operand(offset, LSL, 1));
+
+ // Calculate the base address of the entry.
+ __ mov(base_addr, Operand(key_offset));
+ __ add(base_addr, base_addr, Operand(offset_scratch, LSL, kPointerSizeLog2));
// Check that the key in the entry matches the name.
- __ mov(offsets_base_addr, Operand(key_offset));
- __ ldr(ip, MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits));
+ __ ldr(ip, MemOperand(base_addr, 0));
__ cmp(name, ip);
__ b(ne, &miss);
+ // Check the map matches.
+ __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr));
+ __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ cmp(ip, scratch2);
+ __ b(ne, &miss);
+
// Get the code entry from the cache.
- __ add(offsets_base_addr, offsets_base_addr,
- Operand(value_off_addr - key_off_addr));
- __ ldr(scratch2,
- MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits));
+ Register code = scratch2;
+ scratch2 = no_reg;
+ __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr));
// Check that the flags match what we're looking for.
- __ ldr(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset));
+ Register flags_reg = base_addr;
+ base_addr = no_reg;
+ __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
// It's a nice optimization if this constant is encodable in the bic insn.
uint32_t mask = Code::kFlagsNotUsedInLookup;
ASSERT(__ ImmediateFitsAddrMode1Instruction(mask));
- __ bic(scratch2, scratch2, Operand(mask));
+ __ bic(flags_reg, flags_reg, Operand(mask));
// Using cmn and the negative instead of cmp means we can use movw.
if (flags < 0) {
- __ cmn(scratch2, Operand(-flags));
+ __ cmn(flags_reg, Operand(-flags));
} else {
- __ cmp(scratch2, Operand(flags));
+ __ cmp(flags_reg, Operand(flags));
}
__ b(ne, &miss);
- // Re-load code entry from cache.
- __ ldr(offset,
- MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits));
+#ifdef DEBUG
+ if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
+ __ jmp(&miss);
+ } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
+ __ jmp(&miss);
+ }
+#endif
// Jump to the first instruction in the code stub.
- __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
- __ Jump(offset);
+ __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag));
// Miss: fall through.
__ bind(&miss);
@@ -167,13 +191,14 @@
Register name,
Register scratch,
Register extra,
- Register extra2) {
+ Register extra2,
+ Register extra3) {
Isolate* isolate = masm->isolate();
Label miss;
- // Make sure that code is valid. The shifting code relies on the
- // entry size being 8.
- ASSERT(sizeof(Entry) == 8);
+ // Make sure that code is valid. The multiplying code relies on the
+ // entry size being 12.
+ ASSERT(sizeof(Entry) == 12);
// Make sure the flags does not name a specific type.
ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
@@ -193,6 +218,11 @@
ASSERT(!scratch.is(no_reg));
ASSERT(!extra.is(no_reg));
ASSERT(!extra2.is(no_reg));
+ ASSERT(!extra3.is(no_reg));
+
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
+ extra2, extra3);
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
@@ -201,29 +231,32 @@
__ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
__ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
__ add(scratch, scratch, Operand(ip));
- uint32_t mask = (kPrimaryTableSize - 1) << kHeapObjectTagSize;
+ uint32_t mask = kPrimaryTableSize - 1;
+ // We shift out the last two bits because they are not part of the hash and
+ // they are always 01 for maps.
+ __ mov(scratch, Operand(scratch, LSR, kHeapObjectTagSize));
// Mask down the eor argument to the minimum to keep the immediate
// ARM-encodable.
- __ eor(scratch, scratch, Operand(flags & mask));
+ __ eor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
// Prefer and_ to ubfx here because ubfx takes 2 cycles.
__ and_(scratch, scratch, Operand(mask));
- __ mov(scratch, Operand(scratch, LSR, 1));
// Probe the primary table.
ProbeTable(isolate,
masm,
flags,
kPrimary,
+ receiver,
name,
scratch,
- 1,
extra,
- extra2);
+ extra2,
+ extra3);
// Primary miss: Compute hash for secondary probe.
- __ sub(scratch, scratch, Operand(name, LSR, 1));
- uint32_t mask2 = (kSecondaryTableSize - 1) << (kHeapObjectTagSize - 1);
- __ add(scratch, scratch, Operand((flags >> 1) & mask2));
+ __ sub(scratch, scratch, Operand(name, LSR, kHeapObjectTagSize));
+ uint32_t mask2 = kSecondaryTableSize - 1;
+ __ add(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
__ and_(scratch, scratch, Operand(mask2));
// Probe the secondary table.
@@ -231,15 +264,18 @@
masm,
flags,
kSecondary,
+ receiver,
name,
scratch,
- 1,
extra,
- extra2);
+ extra2,
+ extra3);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.
__ bind(&miss);
+ __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
+ extra2, extra3);
}
diff --git a/src/ast.cc b/src/ast.cc
index 61923bb..b19fc35 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -168,12 +168,15 @@
}
-ObjectLiteral::Property::Property(Literal* key, Expression* value) {
+ObjectLiteral::Property::Property(Literal* key,
+ Expression* value,
+ Isolate* isolate) {
emit_store_ = true;
key_ = key;
value_ = value;
Object* k = *key->handle();
- if (k->IsSymbol() && HEAP->Proto_symbol()->Equals(String::cast(k))) {
+ if (k->IsSymbol() &&
+ isolate->heap()->Proto_symbol()->Equals(String::cast(k))) {
kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL;
@@ -417,8 +420,8 @@
return proxy()->var()->IsStackAllocated();
}
-bool VariableDeclaration::IsInlineable() const {
- return Declaration::IsInlineable() && fun() == NULL;
+bool FunctionDeclaration::IsInlineable() const {
+ return false;
}
@@ -1003,7 +1006,10 @@
}
INCREASE_NODE_COUNT(VariableDeclaration)
+INCREASE_NODE_COUNT(FunctionDeclaration)
INCREASE_NODE_COUNT(ModuleDeclaration)
+INCREASE_NODE_COUNT(ImportDeclaration)
+INCREASE_NODE_COUNT(ExportDeclaration)
INCREASE_NODE_COUNT(ModuleLiteral)
INCREASE_NODE_COUNT(ModuleVariable)
INCREASE_NODE_COUNT(ModulePath)
diff --git a/src/ast.h b/src/ast.h
index 74c4c61..5398775 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -61,7 +61,10 @@
#define DECLARATION_NODE_LIST(V) \
V(VariableDeclaration) \
+ V(FunctionDeclaration) \
V(ModuleDeclaration) \
+ V(ImportDeclaration) \
+ V(ExportDeclaration) \
#define MODULE_NODE_LIST(V) \
V(ModuleLiteral) \
@@ -444,10 +447,10 @@
VariableProxy* proxy() const { return proxy_; }
VariableMode mode() const { return mode_; }
Scope* scope() const { return scope_; }
+ virtual InitializationFlag initialization() const = 0;
virtual bool IsInlineable() const;
virtual Declaration* AsDeclaration() { return this; }
- virtual VariableDeclaration* AsVariableDeclaration() { return NULL; }
protected:
Declaration(VariableProxy* proxy,
@@ -475,22 +478,43 @@
public:
DECLARE_NODE_TYPE(VariableDeclaration)
- virtual VariableDeclaration* AsVariableDeclaration() { return this; }
-
- FunctionLiteral* fun() const { return fun_; } // may be NULL
- virtual bool IsInlineable() const;
+ virtual InitializationFlag initialization() const {
+ return mode() == VAR ? kCreatedInitialized : kNeedsInitialization;
+ }
protected:
template<class> friend class AstNodeFactory;
VariableDeclaration(VariableProxy* proxy,
VariableMode mode,
+ Scope* scope)
+ : Declaration(proxy, mode, scope) {
+ }
+};
+
+
+class FunctionDeclaration: public Declaration {
+ public:
+ DECLARE_NODE_TYPE(FunctionDeclaration)
+
+ FunctionLiteral* fun() const { return fun_; }
+ virtual InitializationFlag initialization() const {
+ return kCreatedInitialized;
+ }
+ virtual bool IsInlineable() const;
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ FunctionDeclaration(VariableProxy* proxy,
+ VariableMode mode,
FunctionLiteral* fun,
Scope* scope)
: Declaration(proxy, mode, scope),
fun_(fun) {
- // At the moment there are no "const functions"'s in JavaScript...
- ASSERT(fun == NULL || mode == VAR || mode == LET);
+ // At the moment there are no "const functions" in JavaScript...
+ ASSERT(mode == VAR || mode == LET);
+ ASSERT(fun != NULL);
}
private:
@@ -503,6 +527,9 @@
DECLARE_NODE_TYPE(ModuleDeclaration)
Module* module() const { return module_; }
+ virtual InitializationFlag initialization() const {
+ return kCreatedInitialized;
+ }
protected:
template<class> friend class AstNodeFactory;
@@ -519,6 +546,48 @@
};
+class ImportDeclaration: public Declaration {
+ public:
+ DECLARE_NODE_TYPE(ImportDeclaration)
+
+ Module* module() const { return module_; }
+ virtual InitializationFlag initialization() const {
+ return kCreatedInitialized;
+ }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ ImportDeclaration(VariableProxy* proxy,
+ Module* module,
+ Scope* scope)
+ : Declaration(proxy, LET, scope),
+ module_(module) {
+ }
+
+ private:
+ Module* module_;
+};
+
+
+class ExportDeclaration: public Declaration {
+ public:
+ DECLARE_NODE_TYPE(ExportDeclaration)
+
+ virtual InitializationFlag initialization() const {
+ return kCreatedInitialized;
+ }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ ExportDeclaration(VariableProxy* proxy,
+ Scope* scope)
+ : Declaration(proxy, LET, scope) {
+ }
+};
+
+
class Module: public AstNode {
// TODO(rossberg): stuff to come...
protected:
@@ -1232,7 +1301,7 @@
PROTOTYPE // Property is __proto__.
};
- Property(Literal* key, Expression* value);
+ Property(Literal* key, Expression* value, Isolate* isolate);
Literal* key() { return key_; }
Expression* value() { return value_; }
@@ -2532,13 +2601,21 @@
VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
VariableMode mode,
- FunctionLiteral* fun,
Scope* scope) {
VariableDeclaration* decl =
- new(zone_) VariableDeclaration(proxy, mode, fun, scope);
+ new(zone_) VariableDeclaration(proxy, mode, scope);
VISIT_AND_RETURN(VariableDeclaration, decl)
}
+ FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* fun,
+ Scope* scope) {
+ FunctionDeclaration* decl =
+ new(zone_) FunctionDeclaration(proxy, mode, fun, scope);
+ VISIT_AND_RETURN(FunctionDeclaration, decl)
+ }
+
ModuleDeclaration* NewModuleDeclaration(VariableProxy* proxy,
Module* module,
Scope* scope) {
@@ -2547,6 +2624,21 @@
VISIT_AND_RETURN(ModuleDeclaration, decl)
}
+ ImportDeclaration* NewImportDeclaration(VariableProxy* proxy,
+ Module* module,
+ Scope* scope) {
+ ImportDeclaration* decl =
+ new(zone_) ImportDeclaration(proxy, module, scope);
+ VISIT_AND_RETURN(ImportDeclaration, decl)
+ }
+
+ ExportDeclaration* NewExportDeclaration(VariableProxy* proxy,
+ Scope* scope) {
+ ExportDeclaration* decl =
+ new(zone_) ExportDeclaration(proxy, scope);
+ VISIT_AND_RETURN(ExportDeclaration, decl)
+ }
+
ModuleLiteral* NewModuleLiteral(Block* body) {
ModuleLiteral* module = new(zone_) ModuleLiteral(body);
VISIT_AND_RETURN(ModuleLiteral, module)
diff --git a/src/compiler.cc b/src/compiler.cc
index cbf53a5..520db34 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -119,6 +119,7 @@
!Serializer::enabled() &&
!function()->flags()->Contains(kDontSelfOptimize) &&
!function()->flags()->Contains(kDontOptimize) &&
+ function()->scope()->allows_lazy_recompilation() &&
(shared_info().is_null() || !shared_info()->optimization_disabled());
}
diff --git a/src/execution.cc b/src/execution.cc
index 00806a7..1f01982 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -872,8 +872,7 @@
#endif
-MaybeObject* Execution::HandleStackGuardInterrupt() {
- Isolate* isolate = Isolate::Current();
+MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
StackGuard* stack_guard = isolate->stack_guard();
if (stack_guard->IsGCRequest()) {
diff --git a/src/execution.h b/src/execution.h
index 014736e..d9ec9dc 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -45,6 +45,10 @@
GC_REQUEST = 1 << 6
};
+
+class Isolate;
+
+
class Execution : public AllStatic {
public:
// Call a function, the caller supplies a receiver and an array
@@ -141,7 +145,8 @@
// If the stack guard is triggered, but it is not an actual
// stack overflow, then handle the interruption accordingly.
- MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt();
+ MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt(
+ Isolate* isolate);
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions.
@@ -158,7 +163,6 @@
class ExecutionAccess;
-class Isolate;
// StackGuard contains the handling of the limits that are used to limit the
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 71af9ae..b8f556d 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -563,6 +563,13 @@
// code-stubs.cc
DEFINE_bool(print_code_stubs, false, "print code stubs")
+DEFINE_bool(test_secondary_stub_cache,
+ false,
+ "test secondary stub cache by disabling the primary one")
+
+DEFINE_bool(test_primary_stub_cache,
+ false,
+ "test primary stub cache by disabling the secondary one")
// codegen-ia32.cc / codegen-arm.cc
DEFINE_bool(print_code, false, "print generated code")
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 9639542..5f3c1d2 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -55,10 +55,22 @@
VariableDeclaration* decl) {
}
+void BreakableStatementChecker::VisitFunctionDeclaration(
+ FunctionDeclaration* decl) {
+}
+
void BreakableStatementChecker::VisitModuleDeclaration(
ModuleDeclaration* decl) {
}
+void BreakableStatementChecker::VisitImportDeclaration(
+ ImportDeclaration* decl) {
+}
+
+void BreakableStatementChecker::VisitExportDeclaration(
+ ExportDeclaration* decl) {
+}
+
void BreakableStatementChecker::VisitModuleLiteral(ModuleLiteral* module) {
}
@@ -569,29 +581,28 @@
isolate()->factory()->NewFixedArray(2 * global_count_, TENURED);
int length = declarations->length();
for (int j = 0, i = 0; i < length; i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
- if (decl != NULL) {
- Variable* var = decl->proxy()->var();
+ Declaration* decl = declarations->at(i);
+ Variable* var = decl->proxy()->var();
- if (var->IsUnallocated()) {
- array->set(j++, *(var->name()));
- if (decl->fun() == NULL) {
- if (var->binding_needs_init()) {
- // In case this binding needs initialization use the hole.
- array->set_the_hole(j++);
- } else {
- array->set_undefined(j++);
- }
+ if (var->IsUnallocated()) {
+ array->set(j++, *(var->name()));
+ FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+ if (fun_decl == NULL) {
+ if (var->binding_needs_init()) {
+ // In case this binding needs initialization use the hole.
+ array->set_the_hole(j++);
} else {
- Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(decl->fun(), script());
- // Check for stack-overflow exception.
- if (function.is_null()) {
- SetStackOverflow();
- return;
- }
- array->set(j++, *function);
+ array->set_undefined(j++);
}
+ } else {
+ Handle<SharedFunctionInfo> function =
+ Compiler::BuildFunctionInfo(fun_decl->fun(), script());
+ // Check for stack-overflow exception.
+ if (function.is_null()) {
+ SetStackOverflow();
+ return;
+ }
+ array->set(j++, *function);
}
}
}
@@ -605,11 +616,26 @@
void FullCodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
+ EmitDeclaration(decl->proxy(), decl->mode(), NULL);
+}
+
+
+void FullCodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
}
void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* decl) {
+ EmitDeclaration(decl->proxy(), decl->mode(), NULL);
+}
+
+
+void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
+ EmitDeclaration(decl->proxy(), decl->mode(), NULL);
+}
+
+
+void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
// TODO(rossberg)
}
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index d09e3a3..cbe1fb5 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -285,6 +285,14 @@
}
+bool HValue::CheckUsesForFlag(Flag f) {
+ for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ if (!it.value()->CheckFlag(f)) return false;
+ }
+ return true;
+}
+
+
HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
Advance();
}
@@ -495,9 +503,9 @@
}
-void HValue::AddNewRange(Range* r) {
- if (!HasRange()) ComputeInitialRange();
- if (!HasRange()) range_ = new Range();
+void HValue::AddNewRange(Range* r, Zone* zone) {
+ if (!HasRange()) ComputeInitialRange(zone);
+ if (!HasRange()) range_ = new(zone) Range();
ASSERT(HasRange());
r->StackUpon(range_);
range_ = r;
@@ -511,9 +519,9 @@
}
-void HValue::ComputeInitialRange() {
+void HValue::ComputeInitialRange(Zone* zone) {
ASSERT(!HasRange());
- range_ = InferRange();
+ range_ = InferRange(zone);
ASSERT(HasRange());
}
@@ -831,12 +839,12 @@
HValue* HConstant::Canonicalize() {
- return HasNoUses() && !IsBlockEntry() ? NULL : this;
+ return HasNoUses() ? NULL : this;
}
HValue* HTypeof::Canonicalize() {
- return HasNoUses() && !IsBlockEntry() ? NULL : this;
+ return HasNoUses() ? NULL : this;
}
@@ -858,6 +866,20 @@
}
+HValue* HAdd::Canonicalize() {
+ if (!representation().IsInteger32()) return this;
+ if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
+ return this;
+}
+
+
+HValue* HSub::Canonicalize() {
+ if (!representation().IsInteger32()) return this;
+ if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
+ return this;
+}
+
+
HValue* HChange::Canonicalize() {
return (from().Equals(to())) ? value() : this;
}
@@ -986,15 +1008,15 @@
}
-Range* HValue::InferRange() {
+Range* HValue::InferRange(Zone* zone) {
// Untagged integer32 cannot be -0, all other representations can.
- Range* result = new Range();
+ Range* result = new(zone) Range();
result->set_can_be_minus_zero(!representation().IsInteger32());
return result;
}
-Range* HChange::InferRange() {
+Range* HChange::InferRange(Zone* zone) {
Range* input_range = value()->range();
if (from().IsInteger32() &&
to().IsTagged() &&
@@ -1002,46 +1024,46 @@
set_type(HType::Smi());
}
Range* result = (input_range != NULL)
- ? input_range->Copy()
- : HValue::InferRange();
+ ? input_range->Copy(zone)
+ : HValue::InferRange(zone);
if (to().IsInteger32()) result->set_can_be_minus_zero(false);
return result;
}
-Range* HConstant::InferRange() {
+Range* HConstant::InferRange(Zone* zone) {
if (has_int32_value_) {
- Range* result = new Range(int32_value_, int32_value_);
+ Range* result = new(zone) Range(int32_value_, int32_value_);
result->set_can_be_minus_zero(false);
return result;
}
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
-Range* HPhi::InferRange() {
+Range* HPhi::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
if (block()->IsLoopHeader()) {
- Range* range = new Range(kMinInt, kMaxInt);
+ Range* range = new(zone) Range(kMinInt, kMaxInt);
return range;
} else {
- Range* range = OperandAt(0)->range()->Copy();
+ Range* range = OperandAt(0)->range()->Copy(zone);
for (int i = 1; i < OperandCount(); ++i) {
range->Union(OperandAt(i)->range());
}
return range;
}
} else {
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
-Range* HAdd::InferRange() {
+Range* HAdd::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
Range* b = right()->range();
- Range* res = a->Copy();
+ Range* res = a->Copy(zone);
if (!res->AddAndCheckOverflow(b)) {
ClearFlag(kCanOverflow);
}
@@ -1049,32 +1071,32 @@
res->set_can_be_minus_zero(m0);
return res;
} else {
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
-Range* HSub::InferRange() {
+Range* HSub::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
Range* b = right()->range();
- Range* res = a->Copy();
+ Range* res = a->Copy(zone);
if (!res->SubAndCheckOverflow(b)) {
ClearFlag(kCanOverflow);
}
res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
return res;
} else {
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
-Range* HMul::InferRange() {
+Range* HMul::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
Range* b = right()->range();
- Range* res = a->Copy();
+ Range* res = a->Copy(zone);
if (!res->MulAndCheckOverflow(b)) {
ClearFlag(kCanOverflow);
}
@@ -1083,14 +1105,14 @@
res->set_can_be_minus_zero(m0);
return res;
} else {
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
-Range* HDiv::InferRange() {
+Range* HDiv::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
- Range* result = new Range();
+ Range* result = new(zone) Range();
if (left()->range()->CanBeMinusZero()) {
result->set_can_be_minus_zero(true);
}
@@ -1108,15 +1130,15 @@
}
return result;
} else {
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
-Range* HMod::InferRange() {
+Range* HMod::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
- Range* result = new Range();
+ Range* result = new(zone) Range();
if (a->CanBeMinusZero() || a->CanBeNegative()) {
result->set_can_be_minus_zero(true);
}
@@ -1125,7 +1147,7 @@
}
return result;
} else {
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
@@ -1324,8 +1346,8 @@
}
-Range* HBitwise::InferRange() {
- if (op() == Token::BIT_XOR) return HValue::InferRange();
+Range* HBitwise::InferRange(Zone* zone) {
+ if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
int32_t left_mask = (left()->range() != NULL)
? left()->range()->Mask()
: 0xffffffff;
@@ -1336,28 +1358,28 @@
? left_mask & right_mask
: left_mask | right_mask;
return (result_mask >= 0)
- ? new Range(0, result_mask)
- : HValue::InferRange();
+ ? new(zone) Range(0, result_mask)
+ : HValue::InferRange(zone);
}
-Range* HSar::InferRange() {
+Range* HSar::InferRange(Zone* zone) {
if (right()->IsConstant()) {
HConstant* c = HConstant::cast(right());
if (c->HasInteger32Value()) {
Range* result = (left()->range() != NULL)
- ? left()->range()->Copy()
- : new Range();
+ ? left()->range()->Copy(zone)
+ : new(zone) Range();
result->Sar(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result;
}
}
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
-Range* HShr::InferRange() {
+Range* HShr::InferRange(Zone* zone) {
if (right()->IsConstant()) {
HConstant* c = HConstant::cast(right());
if (c->HasInteger32Value()) {
@@ -1365,53 +1387,54 @@
if (left()->range()->CanBeNegative()) {
// Only compute bounds if the result always fits into an int32.
return (shift_count >= 1)
- ? new Range(0, static_cast<uint32_t>(0xffffffff) >> shift_count)
- : new Range();
+ ? new(zone) Range(0,
+ static_cast<uint32_t>(0xffffffff) >> shift_count)
+ : new(zone) Range();
} else {
// For positive inputs we can use the >> operator.
Range* result = (left()->range() != NULL)
- ? left()->range()->Copy()
- : new Range();
+ ? left()->range()->Copy(zone)
+ : new(zone) Range();
result->Sar(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result;
}
}
}
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
-Range* HShl::InferRange() {
+Range* HShl::InferRange(Zone* zone) {
if (right()->IsConstant()) {
HConstant* c = HConstant::cast(right());
if (c->HasInteger32Value()) {
Range* result = (left()->range() != NULL)
- ? left()->range()->Copy()
- : new Range();
+ ? left()->range()->Copy(zone)
+ : new(zone) Range();
result->Shl(c->Integer32Value());
result->set_can_be_minus_zero(false);
return result;
}
}
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
-Range* HLoadKeyedSpecializedArrayElement::InferRange() {
+Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
switch (elements_kind()) {
case EXTERNAL_PIXEL_ELEMENTS:
- return new Range(0, 255);
+ return new(zone) Range(0, 255);
case EXTERNAL_BYTE_ELEMENTS:
- return new Range(-128, 127);
+ return new(zone) Range(-128, 127);
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- return new Range(0, 255);
+ return new(zone) Range(0, 255);
case EXTERNAL_SHORT_ELEMENTS:
- return new Range(-32768, 32767);
+ return new(zone) Range(-32768, 32767);
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- return new Range(0, 65535);
+ return new(zone) Range(0, 65535);
default:
- return HValue::InferRange();
+ return HValue::InferRange(zone);
}
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index a0df009..cee90a9 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -236,10 +236,14 @@
int32_t upper() const { return upper_; }
int32_t lower() const { return lower_; }
Range* next() const { return next_; }
- Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
- Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
- Range* Copy() const {
- Range* result = new Range(lower_, upper_);
+ Range* CopyClearLower(Zone* zone) const {
+ return new(zone) Range(kMinInt, upper_);
+ }
+ Range* CopyClearUpper(Zone* zone) const {
+ return new(zone) Range(lower_, kMaxInt);
+ }
+ Range* Copy(Zone* zone) const {
+ Range* result = new(zone) Range(lower_, upper_);
result->set_can_be_minus_zero(CanBeMinusZero());
return result;
}
@@ -641,6 +645,9 @@
void ClearFlag(Flag f) { flags_ &= ~(1 << f); }
bool CheckFlag(Flag f) const { return (flags_ & (1 << f)) != 0; }
+ // Returns true if the flag specified is set for all uses, false otherwise.
+ bool CheckUsesForFlag(Flag f);
+
GVNFlagSet gvn_flags() const { return gvn_flags_; }
void SetGVNFlag(GVNFlag f) { gvn_flags_.Add(f); }
void ClearGVNFlag(GVNFlag f) { gvn_flags_.Remove(f); }
@@ -683,9 +690,9 @@
Range* range() const { return range_; }
bool HasRange() const { return range_ != NULL; }
- void AddNewRange(Range* r);
+ void AddNewRange(Range* r, Zone* zone);
void RemoveLastAddedRange();
- void ComputeInitialRange();
+ void ComputeInitialRange(Zone* zone);
// Representation helpers.
virtual Representation RequiredInputRepresentation(int index) = 0;
@@ -730,7 +737,7 @@
return false;
}
virtual void RepresentationChanged(Representation to) { }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
virtual void DeleteFromGraph() = 0;
virtual void InternalSetOperandAt(int index, HValue* value) = 0;
void clear_block() {
@@ -820,6 +827,8 @@
bool has_position() const { return position_ != RelocInfo::kNoPosition; }
void set_position(int position) { position_ = position; }
+ bool CanTruncateToInt32() const { return CheckFlag(kTruncatingToInt32); }
+
virtual LInstruction* CompileToLithium(LChunkBuilder* builder) = 0;
#ifdef DEBUG
@@ -1117,10 +1126,6 @@
return reinterpret_cast<HUnaryOperation*>(value);
}
- virtual bool CanTruncateToInt32() const {
- return CheckFlag(kTruncatingToInt32);
- }
-
HValue* value() { return OperandAt(0); }
virtual void PrintDataTo(StringStream* stream);
};
@@ -1208,7 +1213,7 @@
return from();
}
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
virtual void PrintDataTo(StringStream* stream);
@@ -1244,16 +1249,13 @@
: HUnaryOperation(value) {
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
+ SetFlag(kTruncatingToInt32);
}
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
- virtual bool CanTruncateToInt32() const {
- return true;
- }
-
virtual HValue* Canonicalize() {
if (value()->representation().IsInteger32()) {
return value();
@@ -2299,7 +2301,7 @@
return Representation::None();
}
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
virtual Representation RequiredInputRepresentation(int index) {
return representation();
}
@@ -2477,7 +2479,7 @@
DECLARE_CONCRETE_INSTRUCTION(Constant)
protected:
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
virtual bool DataEquals(HValue* other) {
HConstant* other_constant = HConstant::cast(other);
@@ -3150,12 +3152,14 @@
virtual HType CalculateInferredType();
+ virtual HValue* Canonicalize();
+
DECLARE_CONCRETE_INSTRUCTION(Add)
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
};
@@ -3168,6 +3172,8 @@
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+ virtual HValue* Canonicalize();
+
static HInstruction* NewHSub(Zone* zone,
HValue* context,
HValue* left,
@@ -3178,7 +3184,7 @@
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
};
@@ -3206,7 +3212,7 @@
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
};
@@ -3239,7 +3245,7 @@
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
};
@@ -3253,7 +3259,6 @@
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
-
static HInstruction* NewHDiv(Zone* zone,
HValue* context,
HValue* left,
@@ -3264,7 +3269,7 @@
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
};
@@ -3296,7 +3301,7 @@
return op() == HBitwise::cast(other)->op();
}
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
private:
Token::Value op_;
@@ -3308,7 +3313,7 @@
HShl(HValue* context, HValue* left, HValue* right)
: HBitwiseBinaryOperation(context, left, right) { }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
static HInstruction* NewHShl(Zone* zone,
HValue* context,
@@ -3327,7 +3332,7 @@
HShr(HValue* context, HValue* left, HValue* right)
: HBitwiseBinaryOperation(context, left, right) { }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
static HInstruction* NewHShr(Zone* zone,
HValue* context,
@@ -3346,7 +3351,7 @@
HSar(HValue* context, HValue* left, HValue* right)
: HBitwiseBinaryOperation(context, left, right) { }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
static HInstruction* NewHSar(Zone* zone,
HValue* context,
@@ -3936,7 +3941,7 @@
HValue* key() { return OperandAt(1); }
ElementsKind elements_kind() const { return elements_kind_; }
- virtual Range* InferRange();
+ virtual Range* InferRange(Zone* zone);
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
@@ -4304,8 +4309,8 @@
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange() {
- return new Range(0, String::kMaxUC16CharCode);
+ virtual Range* InferRange(Zone* zone) {
+ return new(zone) Range(0, String::kMaxUC16CharCode);
}
};
@@ -4357,8 +4362,8 @@
protected:
virtual bool DataEquals(HValue* other) { return true; }
- virtual Range* InferRange() {
- return new Range(0, String::kMaxLength);
+ virtual Range* InferRange(Zone* zone) {
+ return new(zone) Range(0, String::kMaxLength);
}
};
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 4307a0d..ffd3d1e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -979,7 +979,8 @@
class HRangeAnalysis BASE_EMBEDDED {
public:
- explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {}
+ explicit HRangeAnalysis(HGraph* graph) :
+ graph_(graph), zone_(graph->isolate()->zone()), changed_ranges_(16) { }
void Analyze();
@@ -993,6 +994,7 @@
void AddRange(HValue* value, Range* range);
HGraph* graph_;
+ Zone* zone_;
ZoneList<HValue*> changed_ranges_;
};
@@ -1079,14 +1081,14 @@
if (op == Token::EQ || op == Token::EQ_STRICT) {
// The same range has to apply for value.
- new_range = range->Copy();
+ new_range = range->Copy(zone_);
} else if (op == Token::LT || op == Token::LTE) {
- new_range = range->CopyClearLower();
+ new_range = range->CopyClearLower(zone_);
if (op == Token::LT) {
new_range->AddConstant(-1);
}
} else if (op == Token::GT || op == Token::GTE) {
- new_range = range->CopyClearUpper();
+ new_range = range->CopyClearUpper(zone_);
if (op == Token::GT) {
new_range->AddConstant(1);
}
@@ -1101,7 +1103,7 @@
void HRangeAnalysis::InferRange(HValue* value) {
ASSERT(!value->HasRange());
if (!value->representation().IsNone()) {
- value->ComputeInitialRange();
+ value->ComputeInitialRange(zone_);
Range* range = value->range();
TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
value->id(),
@@ -1122,7 +1124,7 @@
void HRangeAnalysis::AddRange(HValue* value, Range* range) {
Range* original_range = value->range();
- value->AddNewRange(range);
+ value->AddNewRange(range, zone_);
changed_ranges_.Add(value);
Range* new_range = value->range();
TraceRange("Updated range of %d set to [%d,%d]\n",
@@ -2065,13 +2067,9 @@
for (int i = 0; i < phi_list()->length(); i++) {
HPhi* phi = phi_list()->at(i);
if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue;
- for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
- HValue* use = it.value();
- if (!use->CheckFlag(HValue::kTruncatingToInt32)) {
- phi->ClearFlag(HValue::kTruncatingToInt32);
- change = true;
- break;
- }
+ if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) {
+ phi->ClearFlag(HValue::kTruncatingToInt32);
+ change = true;
}
}
}
@@ -2466,7 +2464,7 @@
// Handle implicit declaration of the function name in named function
// expressions before other declarations.
if (scope->is_function_scope() && scope->function() != NULL) {
- HandleVariableDeclaration(scope->function(), CONST, NULL, NULL);
+ HandleDeclaration(scope->function(), CONST, NULL, NULL);
}
VisitDeclarations(scope->declarations());
AddSimulate(AstNode::kDeclarationsId);
@@ -6826,20 +6824,16 @@
}
-void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
- UNREACHABLE();
-}
-
void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
int length = declarations->length();
int global_count = 0;
for (int i = 0; i < declarations->length(); i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
- if (decl == NULL) continue;
- HandleVariableDeclaration(decl->proxy(),
- decl->mode(),
- decl->fun(),
- &global_count);
+ Declaration* decl = declarations->at(i);
+ FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+ HandleDeclaration(decl->proxy(),
+ decl->mode(),
+ fun_decl != NULL ? fun_decl->fun() : NULL,
+ &global_count);
}
// Batch declare global functions and variables.
@@ -6847,13 +6841,13 @@
Handle<FixedArray> array =
isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
for (int j = 0, i = 0; i < length; i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
- if (decl == NULL) continue;
+ Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var();
if (var->IsUnallocated()) {
array->set(j++, *(var->name()));
- if (decl->fun() == NULL) {
+ FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+ if (fun_decl == NULL) {
if (var->binding_needs_init()) {
// In case this binding needs initialization use the hole.
array->set_the_hole(j++);
@@ -6862,7 +6856,7 @@
}
} else {
Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(decl->fun(), info()->script());
+ Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script());
// Check for stack-overflow exception.
if (function.is_null()) {
SetStackOverflow();
@@ -6884,10 +6878,10 @@
}
-void HGraphBuilder::HandleVariableDeclaration(VariableProxy* proxy,
- VariableMode mode,
- FunctionLiteral* function,
- int* global_count) {
+void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* function,
+ int* global_count) {
Variable* var = proxy->var();
bool binding_needs_init =
(mode == CONST || mode == CONST_HARMONY || mode == LET);
@@ -6923,8 +6917,28 @@
}
+void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
+ UNREACHABLE();
+}
+
+
+void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
+ UNREACHABLE();
+}
+
+
void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
- // TODO(rossberg)
+ UNREACHABLE();
+}
+
+
+void HGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
+ UNREACHABLE();
+}
+
+
+void HGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
+ UNREACHABLE();
}
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 50c76cb..b0d67eb 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -870,10 +870,10 @@
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
- void HandleVariableDeclaration(VariableProxy* proxy,
- VariableMode mode,
- FunctionLiteral* function,
- int* global_count);
+ void HandleDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* function,
+ int* global_count);
void VisitDelete(UnaryOperation* expr);
void VisitVoid(UnaryOperation* expr);
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 647ba6a..7a1a893 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -2321,7 +2321,7 @@
: chunk_(NULL),
info_(info),
graph_(graph),
- isolate_(graph->isolate()),
+ zone_(graph->isolate()->zone()),
status_(UNUSED),
current_instruction_(NULL),
current_block_(NULL),
@@ -2351,7 +2351,7 @@
LChunk* chunk() const { return chunk_; }
CompilationInfo* info() const { return info_; }
HGraph* graph() const { return graph_; }
- Zone* zone() { return isolate_->zone(); }
+ Zone* zone() { return zone_; }
bool is_unused() const { return status_ == UNUSED; }
bool is_building() const { return status_ == BUILDING; }
@@ -2460,7 +2460,7 @@
LChunk* chunk_;
CompilationInfo* info_;
HGraph* const graph_;
- Isolate* isolate_;
+ Zone* zone_;
Status status_;
HInstruction* current_instruction_;
HBasicBlock* current_block_;
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index e613a06..2c9b60c 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -1085,7 +1085,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt();
+ MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
int delta = code_handle->address() - re_code->address();
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 56484af..de71818 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -44,19 +44,30 @@
Code::Flags flags,
StubCache::Table table,
Register name,
+ Register receiver,
+ // Number of the cache entry pointer-size scaled.
Register offset,
Register extra) {
ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
+ ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
Label miss;
+ // Multiply by 3 because there are 3 fields per entry (name, code, map).
+ __ lea(offset, Operand(offset, offset, times_2, 0));
+
if (extra.is_valid()) {
// Get the code entry from the cache.
- __ mov(extra, Operand::StaticArray(offset, times_2, value_offset));
+ __ mov(extra, Operand::StaticArray(offset, times_1, value_offset));
// Check that the key in the entry matches the name.
- __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
+ __ cmp(name, Operand::StaticArray(offset, times_1, key_offset));
+ __ j(not_equal, &miss);
+
+ // Check the map matches.
+ __ mov(offset, Operand::StaticArray(offset, times_1, map_offset));
+ __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset));
__ j(not_equal, &miss);
// Check that the flags match what we're looking for.
@@ -65,6 +76,14 @@
__ cmp(offset, flags);
__ j(not_equal, &miss);
+#ifdef DEBUG
+ if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
+ __ jmp(&miss);
+ } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
+ __ jmp(&miss);
+ }
+#endif
+
// Jump to the first instruction in the code stub.
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(extra);
@@ -75,11 +94,19 @@
__ push(offset);
// Check that the key in the entry matches the name.
- __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
+ __ cmp(name, Operand::StaticArray(offset, times_1, key_offset));
__ j(not_equal, &miss);
+ // Check the map matches.
+ __ mov(offset, Operand::StaticArray(offset, times_1, map_offset));
+ __ cmp(offset, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ j(not_equal, &miss);
+
+ // Restore offset register.
+ __ mov(offset, Operand(esp, 0));
+
// Get the code entry from the cache.
- __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
+ __ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
// Check that the flags match what we're looking for.
__ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
@@ -87,9 +114,17 @@
__ cmp(offset, flags);
__ j(not_equal, &miss);
+#ifdef DEBUG
+ if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
+ __ jmp(&miss);
+ } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
+ __ jmp(&miss);
+ }
+#endif
+
// Restore offset and re-load code entry from cache.
__ pop(offset);
- __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
+ __ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
// Jump to the first instruction in the code stub.
__ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
@@ -159,12 +194,13 @@
Register name,
Register scratch,
Register extra,
- Register extra2) {
+ Register extra2,
+ Register extra3) {
Label miss;
- // Assert that code is valid. The shifting code relies on the entry size
- // being 8.
- ASSERT(sizeof(Entry) == 8);
+ // Assert that code is valid. The multiplying code relies on the entry size
+ // being 12.
+ ASSERT(sizeof(Entry) == 12);
// Assert the flags do not name a specific type.
ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
@@ -176,37 +212,51 @@
ASSERT(!extra.is(name));
ASSERT(!extra.is(scratch));
- // Assert scratch and extra registers are valid, and extra2 is unused.
+ // Assert scratch and extra registers are valid, and extra2/3 are unused.
ASSERT(!scratch.is(no_reg));
ASSERT(extra2.is(no_reg));
+ ASSERT(extra3.is(no_reg));
+
+ Register offset = scratch;
+ scratch = no_reg;
+
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
// Get the map of the receiver and compute the hash.
- __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
- __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
- __ xor_(scratch, flags);
- __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
+ __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
+ __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ xor_(offset, flags);
+ // We mask out the last two bits because they are not part of the hash and
+ // they are always 01 for maps. Also in the two 'and' instructions below.
+ __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
+ // ProbeTable expects the offset to be pointer scaled, which it is, because
+ // the heap object tag size is 2 and the pointer size log 2 is also 2.
+ ASSERT(kHeapObjectTagSize == kPointerSizeLog2);
// Probe the primary table.
- ProbeTable(isolate(), masm, flags, kPrimary, name, scratch, extra);
+ ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra);
// Primary miss: Compute hash for secondary probe.
- __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
- __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
- __ xor_(scratch, flags);
- __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
- __ sub(scratch, name);
- __ add(scratch, Immediate(flags));
- __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
+ __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
+ __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ xor_(offset, flags);
+ __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
+ __ sub(offset, name);
+ __ add(offset, Immediate(flags));
+ __ and_(offset, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
// Probe the secondary table.
- ProbeTable(isolate(), masm, flags, kSecondary, name, scratch, extra);
+ ProbeTable(
+ isolate(), masm, flags, kSecondary, name, receiver, offset, extra);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.
__ bind(&miss);
+ __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
}
diff --git a/src/isolate.cc b/src/isolate.cc
index 128136f..93742bd 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1836,13 +1836,12 @@
#ifdef ENABLE_DEBUGGER_SUPPORT
debug_->SetUp(create_heap_objects);
#endif
- stub_cache_->Initialize(create_heap_objects);
// If we are deserializing, read the state into the now-empty heap.
if (des != NULL) {
des->Deserialize();
- stub_cache_->Initialize(true);
}
+ stub_cache_->Initialize();
// Finish initialization of ThreadLocal after deserialization is done.
clear_pending_exception();
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 82b4958..7e695bb 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -175,7 +175,8 @@
case JSRegExp::IRREGEXP: {
Handle<Object> result =
IrregexpExec(regexp, subject, index, last_match_info);
- ASSERT(!result.is_null() || Isolate::Current()->has_pending_exception());
+ ASSERT(!result.is_null() ||
+ regexp->GetIsolate()->has_pending_exception());
return result;
}
default:
@@ -527,6 +528,7 @@
Handle<String> subject,
int previous_index,
Handle<JSArray> last_match_info) {
+ Isolate* isolate = jsregexp->GetIsolate();
ASSERT_EQ(jsregexp->TypeTag(), JSRegExp::IRREGEXP);
// Prepare space for the return values.
@@ -542,11 +544,11 @@
int required_registers = RegExpImpl::IrregexpPrepare(jsregexp, subject);
if (required_registers < 0) {
// Compiling failed with an exception.
- ASSERT(Isolate::Current()->has_pending_exception());
+ ASSERT(isolate->has_pending_exception());
return Handle<Object>::null();
}
- OffsetsVector registers(required_registers);
+ OffsetsVector registers(required_registers, isolate);
IrregexpResult res = RegExpImpl::IrregexpExecOnce(
jsregexp, subject, previous_index, Vector<int>(registers.vector(),
@@ -568,11 +570,11 @@
return last_match_info;
}
if (res == RE_EXCEPTION) {
- ASSERT(Isolate::Current()->has_pending_exception());
+ ASSERT(isolate->has_pending_exception());
return Handle<Object>::null();
}
ASSERT(res == RE_FAILURE);
- return Isolate::Current()->factory()->null_value();
+ return isolate->factory()->null_value();
}
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 42c76fb..8875de9 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -1466,12 +1466,12 @@
class OffsetsVector {
public:
- explicit inline OffsetsVector(int num_registers)
+ inline OffsetsVector(int num_registers, Isolate* isolate)
: offsets_vector_length_(num_registers) {
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
vector_ = NewArray<int>(offsets_vector_length_);
} else {
- vector_ = Isolate::Current()->jsregexp_static_offsets_vector();
+ vector_ = isolate->jsregexp_static_offsets_vector();
}
}
inline ~OffsetsVector() {
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index cc11235..715ff95 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -1008,6 +1008,11 @@
NullCallWrapper(), CALL_AS_METHOD);
}
+ // Store offset of return address for deoptimizer.
+ if (!is_api_function && !count_constructions) {
+ masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
+ }
+
// Restore context from the frame.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -1777,7 +1782,9 @@
__ Call(a3);
+ // Store offset of return address for deoptimizer.
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
+
// Exit frame and return.
LeaveArgumentsAdaptorFrame(masm);
__ Ret();
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 6f79225..4717847 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -5363,16 +5363,18 @@
// A monomorphic miss (i.e, here the cache is not uninitialized) goes
// megamorphic.
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
- __ Branch(&done, eq, a3, Operand(at));
+
+ __ Branch(USE_DELAY_SLOT, &done, eq, a3, Operand(at));
+ // An uninitialized cache is patched with the function.
+ // Store a1 in the delay slot. This may or may not get overwritten depending
+ // on the result of the comparison.
+ __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
+ // No need for a write barrier here - cells are rescanned.
+
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ sw(at, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
- __ Branch(&done);
-
- // An uninitialized cache is patched with the function.
- __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
- // No need for a write barrier here - cells are rescanned.
__ bind(&done);
}
diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc
index 78720f4..7e0a53a 100644
--- a/src/mips/deoptimizer-mips.cc
+++ b/src/mips/deoptimizer-mips.cc
@@ -355,7 +355,6 @@
}
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
- unsigned input_frame_size = input_->GetFrameSize();
unsigned output_frame_size = height_in_bytes + fixed_frame_size;
// Allocate and store the output frame description.
@@ -377,16 +376,13 @@
// Compute the incoming parameter translation.
int parameter_count = height;
unsigned output_offset = output_frame_size;
- unsigned input_offset = input_frame_size;
for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize;
DoTranslateCommand(iterator, frame_index, output_offset);
}
- input_offset -= (parameter_count * kPointerSize);
// Read caller's PC from the previous frame.
output_offset -= kPointerSize;
- input_offset -= kPointerSize;
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
output_frame->SetFrameSlot(output_offset, callers_pc);
if (FLAG_trace_deopt) {
@@ -396,7 +392,6 @@
// Read caller's FP from the previous frame, and set this frame's FP.
output_offset -= kPointerSize;
- input_offset -= kPointerSize;
intptr_t value = output_[frame_index - 1]->GetFp();
output_frame->SetFrameSlot(output_offset, value);
intptr_t fp_value = top_address + output_offset;
@@ -408,7 +403,6 @@
// A marker value is used in place of the context.
output_offset -= kPointerSize;
- input_offset -= kPointerSize;
intptr_t context = reinterpret_cast<intptr_t>(
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
output_frame->SetFrameSlot(output_offset, context);
@@ -419,7 +413,6 @@
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
output_offset -= kPointerSize;
- input_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
@@ -429,7 +422,6 @@
// Number of incoming arguments.
output_offset -= kPointerSize;
- input_offset -= kPointerSize;
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
@@ -449,6 +441,119 @@
}
+void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
+ int frame_index) {
+ JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
+ unsigned height = iterator->Next();
+ unsigned height_in_bytes = height * kPointerSize;
+ if (FLAG_trace_deopt) {
+ PrintF(" translating construct stub => height=%d\n", height_in_bytes);
+ }
+
+ unsigned fixed_frame_size = 7 * kPointerSize;
+ unsigned output_frame_size = height_in_bytes + fixed_frame_size;
+
+ // Allocate and store the output frame description.
+ FrameDescription* output_frame =
+ new(output_frame_size) FrameDescription(output_frame_size, function);
+ output_frame->SetFrameType(StackFrame::CONSTRUCT);
+
+ // Construct stub can not be topmost or bottommost.
+ ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
+ ASSERT(output_[frame_index] == NULL);
+ output_[frame_index] = output_frame;
+
+ // The top address of the frame is computed from the previous
+ // frame's top and this frame's size.
+ uint32_t top_address;
+ top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+ output_frame->SetTop(top_address);
+
+ // Compute the incoming parameter translation.
+ int parameter_count = height;
+ unsigned output_offset = output_frame_size;
+ for (int i = 0; i < parameter_count; ++i) {
+ output_offset -= kPointerSize;
+ DoTranslateCommand(iterator, frame_index, output_offset);
+ }
+
+ // Read caller's PC from the previous frame.
+ output_offset -= kPointerSize;
+ intptr_t callers_pc = output_[frame_index - 1]->GetPc();
+ output_frame->SetFrameSlot(output_offset, callers_pc);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
+ top_address + output_offset, output_offset, callers_pc);
+ }
+
+ // Read caller's FP from the previous frame, and set this frame's FP.
+ output_offset -= kPointerSize;
+ intptr_t value = output_[frame_index - 1]->GetFp();
+ output_frame->SetFrameSlot(output_offset, value);
+ intptr_t fp_value = top_address + output_offset;
+ output_frame->SetFp(fp_value);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
+ fp_value, output_offset, value);
+ }
+
+ // The context can be gotten from the previous frame.
+ output_offset -= kPointerSize;
+ value = output_[frame_index - 1]->GetContext();
+ output_frame->SetFrameSlot(output_offset, value);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n",
+ top_address + output_offset, output_offset, value);
+ }
+
+ // A marker value is used in place of the function.
+ output_offset -= kPointerSize;
+ value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
+ output_frame->SetFrameSlot(output_offset, value);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
+ top_address + output_offset, output_offset, value);
+ }
+
+ // Number of incoming arguments.
+ output_offset -= kPointerSize;
+ value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
+ output_frame->SetFrameSlot(output_offset, value);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
+ top_address + output_offset, output_offset, value, height - 1);
+ }
+
+ // Constructor function being invoked by the stub.
+ output_offset -= kPointerSize;
+ value = reinterpret_cast<intptr_t>(function);
+ output_frame->SetFrameSlot(output_offset, value);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; constructor function\n",
+ top_address + output_offset, output_offset, value);
+ }
+
+ // The newly allocated object was passed as receiver in the artificial
+ // constructor stub environment created by HEnvironment::CopyForInlining().
+ output_offset -= kPointerSize;
+ value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
+ output_frame->SetFrameSlot(output_offset, value);
+ if (FLAG_trace_deopt) {
+ PrintF(" 0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
+ top_address + output_offset, output_offset, value);
+ }
+
+ ASSERT(0 == output_offset);
+
+ Builtins* builtins = isolate_->builtins();
+ Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
+ uint32_t pc = reinterpret_cast<uint32_t>(
+ construct_stub->instruction_start() +
+ isolate_->heap()->construct_stub_deopt_pc_offset()->value());
+ output_frame->SetPc(pc);
+}
+
+
// This code is very similar to ia32/arm code, but relies on register names
// (fp, sp) and how the frame is laid out.
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
@@ -561,9 +666,8 @@
value = reinterpret_cast<intptr_t>(function->context());
}
output_frame->SetFrameSlot(output_offset, value);
- if (is_topmost) {
- output_frame->SetRegister(cp.code(), value);
- }
+ output_frame->SetContext(value);
+ if (is_topmost) output_frame->SetRegister(cp.code(), value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n",
top_address + output_offset, output_offset, value);
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index d6e7a44..5559788 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -952,7 +952,8 @@
Register null_value = t1;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ Branch(&exit, eq, a0, Operand(null_value));
-
+ PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
+ __ mov(a0, v0);
// Convert the object to a JS object.
Label convert, done_convert;
__ JumpIfSmi(a0, &convert);
@@ -975,44 +976,7 @@
// the JSObject::IsSimpleEnum cache validity checks. If we cannot
// guarantee cache validity, call the runtime system to check cache
// validity or get the property names in a fixed array.
- Label next;
- // Preload a couple of values used in the loop.
- Register empty_fixed_array_value = t2;
- __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
- Register empty_descriptor_array_value = t3;
- __ LoadRoot(empty_descriptor_array_value,
- Heap::kEmptyDescriptorArrayRootIndex);
- __ mov(a1, a0);
- __ bind(&next);
-
- // Check that there are no elements. Register a1 contains the
- // current JS object we've reached through the prototype chain.
- __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
- __ Branch(&call_runtime, ne, a2, Operand(empty_fixed_array_value));
-
- // Check that instance descriptors are not empty so that we can
- // check for an enum cache. Leave the map in a2 for the subsequent
- // prototype load.
- __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
- __ lw(a3, FieldMemOperand(a2, Map::kInstanceDescriptorsOrBitField3Offset));
- __ JumpIfSmi(a3, &call_runtime);
-
- // Check that there is an enum cache in the non-empty instance
- // descriptors (a3). This is the case if the next enumeration
- // index field does not contain a smi.
- __ lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumerationIndexOffset));
- __ JumpIfSmi(a3, &call_runtime);
-
- // For all objects but the receiver, check that the cache is empty.
- Label check_prototype;
- __ Branch(&check_prototype, eq, a1, Operand(a0));
- __ lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumCacheBridgeCacheOffset));
- __ Branch(&call_runtime, ne, a3, Operand(empty_fixed_array_value));
-
- // Load the prototype from the map and loop if non-null.
- __ bind(&check_prototype);
- __ lw(a1, FieldMemOperand(a2, Map::kPrototypeOffset));
- __ Branch(&next, ne, a1, Operand(null_value));
+ __ CheckEnumCache(null_value, &call_runtime);
// The enum cache is valid. Load the map of the object being
// iterated over and use the cache for the iteration.
@@ -1064,6 +1028,7 @@
__ Push(a1, a0); // Fixed array length (as smi) and initial index.
// Generate code for doing the condition check.
+ PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&loop);
// Load the current count to a0, load the length to a1.
__ lw(a0, MemOperand(sp, 0 * kPointerSize));
@@ -1108,7 +1073,7 @@
__ mov(result_register(), a3);
// Perform the assignment as if via '='.
{ EffectContext context(this);
- EmitAssignment(stmt->each(), stmt->AssignmentId());
+ EmitAssignment(stmt->each());
}
// Generate code for the body of the loop.
@@ -1129,6 +1094,7 @@
__ Drop(5);
// Exit and decrement the loop depth.
+ PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
decrement_loop_depth();
}
@@ -1899,7 +1865,7 @@
}
-void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
+void FullCodeGenerator::EmitAssignment(Expression* expr) {
// Invalid left-hand sides are rewritten to have a 'throw
// ReferenceError' on the left-hand side.
if (!expr->IsValidLeftHandSide()) {
@@ -1951,7 +1917,6 @@
break;
}
}
- PrepareForBailoutForId(bailout_ast_id, TOS_REG);
context()->Plug(v0);
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index f600904..5650d42 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -447,10 +447,18 @@
WriteTranslation(environment->outer(), translation);
int closure_id = DefineDeoptimizationLiteral(environment->closure());
- if (environment->is_arguments_adaptor()) {
- translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
- } else {
- translation->BeginJSFrame(environment->ast_id(), closure_id, height);
+ switch (environment->frame_type()) {
+ case JS_FUNCTION:
+ translation->BeginJSFrame(environment->ast_id(), closure_id, height);
+ break;
+ case JS_CONSTRUCT:
+ translation->BeginConstructStubFrame(closure_id, translation_size);
+ break;
+ case ARGUMENTS_ADAPTOR:
+ translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
+ break;
+ default:
+ UNREACHABLE();
}
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
@@ -580,7 +588,7 @@
int jsframe_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count;
- if (!e->is_arguments_adaptor()) {
+ if (e->frame_type() == JS_FUNCTION) {
++jsframe_count;
}
}
@@ -4828,6 +4836,89 @@
}
+void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
+ Register result = ToRegister(instr->result());
+ Register object = ToRegister(instr->object());
+ __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+ DeoptimizeIf(eq, instr->environment(), object, Operand(at));
+
+ Register null_value = t1;
+ __ LoadRoot(null_value, Heap::kNullValueRootIndex);
+ DeoptimizeIf(eq, instr->environment(), object, Operand(null_value));
+
+ __ And(at, object, kSmiTagMask);
+ DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
+
+ STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
+ __ GetObjectType(object, a1, a1);
+ DeoptimizeIf(le, instr->environment(), a1, Operand(LAST_JS_PROXY_TYPE));
+
+ Label use_cache, call_runtime;
+ ASSERT(object.is(a0));
+ __ CheckEnumCache(null_value, &call_runtime);
+
+ __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset));
+ __ Branch(&use_cache);
+
+ // Get the set of properties to enumerate.
+ __ bind(&call_runtime);
+ __ push(object);
+ CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
+
+ __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
+ ASSERT(result.is(v0));
+ __ LoadRoot(at, Heap::kMetaMapRootIndex);
+ DeoptimizeIf(ne, instr->environment(), a1, Operand(at));
+ __ bind(&use_cache);
+}
+
+
+void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
+ Register map = ToRegister(instr->map());
+ Register result = ToRegister(instr->result());
+ __ LoadInstanceDescriptors(map, result);
+ __ lw(result,
+ FieldMemOperand(result, DescriptorArray::kEnumerationIndexOffset));
+ __ lw(result,
+ FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
+ DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
+}
+
+
+void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
+ Register object = ToRegister(instr->value());
+ Register map = ToRegister(instr->map());
+ __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
+ DeoptimizeIf(ne, instr->environment(), map, Operand(scratch0()));
+}
+
+
+void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
+ Register object = ToRegister(instr->object());
+ Register index = ToRegister(instr->index());
+ Register result = ToRegister(instr->result());
+ Register scratch = scratch0();
+
+ Label out_of_object, done;
+ __ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg));
+ __ sll(scratch, index, kPointerSizeLog2 - kSmiTagSize); // In delay slot.
+
+ STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
+ __ Addu(scratch, object, scratch);
+ __ lw(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
+
+ __ Branch(&done);
+
+ __ bind(&out_of_object);
+ __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ // Index is equal to negated out of object property index plus 1.
+ __ Subu(scratch, result, scratch);
+ __ lw(result, FieldMemOperand(scratch,
+ FixedArray::kHeaderSize - kPointerSize));
+ __ bind(&done);
+}
+
+
#undef __
} } // namespace v8::internal
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 0d78845..4d86882 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -476,7 +476,7 @@
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
- LInstructionGap* gap = new LInstructionGap(block);
+ LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
int index = -1;
if (instr->IsControl()) {
instructions_.Add(gap);
@@ -551,7 +551,7 @@
LChunk* LChunkBuilder::Build() {
ASSERT(is_unused());
- chunk_ = new LChunk(info(), graph());
+ chunk_ = new(zone()) LChunk(info(), graph());
HPhase phase("Building chunk", chunk_);
status_ = BUILDING;
const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
@@ -582,14 +582,14 @@
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new LUnallocated(LUnallocated::FIXED_REGISTER,
- Register::ToAllocationIndex(reg));
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
- return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
- DoubleRegister::ToAllocationIndex(reg));
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg));
}
@@ -604,29 +604,29 @@
LOperand* LChunkBuilder::UseRegister(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
}
LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
return Use(value,
- new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
- LUnallocated::USED_AT_START));
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
+ LUnallocated::USED_AT_START));
}
LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
}
LOperand* LChunkBuilder::Use(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::NONE));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
}
LOperand* LChunkBuilder::UseAtStart(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::NONE,
+ return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
LUnallocated::USED_AT_START));
}
@@ -662,7 +662,7 @@
LOperand* LChunkBuilder::UseAny(HValue* value) {
return value->IsConstant()
? chunk_->DefineConstantOperand(HConstant::cast(value))
- : Use(value, new LUnallocated(LUnallocated::ANY));
+ : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
}
@@ -688,21 +688,24 @@
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsRegister(
LTemplateInstruction<1, I, T>* instr) {
- return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
}
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsSpilled(
LTemplateInstruction<1, I, T>* instr, int index) {
- return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
}
template<int I, int T>
LInstruction* LChunkBuilder::DefineSameAsFirst(
LTemplateInstruction<1, I, T>* instr) {
- return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
}
@@ -784,13 +787,14 @@
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
ASSERT(!instr->HasPointerMap());
- instr->set_pointer_map(new LPointerMap(position_));
+ instr->set_pointer_map(new(zone()) LPointerMap(position_));
return instr;
}
LUnallocated* LChunkBuilder::TempRegister() {
- LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
+ LUnallocated* operand =
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
return operand;
@@ -812,17 +816,17 @@
LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
- return new LLabel(instr->block());
+ return new(zone()) LLabel(instr->block());
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
- return AssignEnvironment(new LDeoptimize);
+ return AssignEnvironment(new(zone()) LDeoptimize);
}
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
- return AssignEnvironment(new LDeoptimize);
+ return AssignEnvironment(new(zone()) LDeoptimize);
}
@@ -834,7 +838,7 @@
LOperand* left = UseFixed(instr->left(), a1);
LOperand* right = UseFixed(instr->right(), a0);
- LArithmeticT* result = new LArithmeticT(op, left, right);
+ LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -868,7 +872,7 @@
}
LInstruction* result =
- DefineAsRegister(new LShiftI(op, left, right, does_deopt));
+ DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
return does_deopt ? AssignEnvironment(result) : result;
}
@@ -881,7 +885,7 @@
ASSERT(op != Token::MOD);
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- LArithmeticD* result = new LArithmeticD(op, left, right);
+ LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
return DefineAsRegister(result);
}
@@ -899,7 +903,8 @@
ASSERT(right->representation().IsTagged());
LOperand* left_operand = UseFixed(left, a1);
LOperand* right_operand = UseFixed(right, a0);
- LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
+ LArithmeticT* result =
+ new(zone()) LArithmeticT(op, left_operand, right_operand);
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -995,15 +1000,17 @@
LEnvironment* outer =
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
int ast_id = hydrogen_env->ast_id();
- ASSERT(ast_id != AstNode::kNoNumber || hydrogen_env->is_arguments_adaptor());
+ ASSERT(ast_id != AstNode::kNoNumber ||
+ hydrogen_env->frame_type() != JS_FUNCTION);
int value_count = hydrogen_env->length();
- LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
- hydrogen_env->is_arguments_adaptor(),
- ast_id,
- hydrogen_env->parameter_count(),
- argument_count_,
- value_count,
- outer);
+ LEnvironment* result = new(zone()) LEnvironment(
+ hydrogen_env->closure(),
+ hydrogen_env->frame_type(),
+ ast_id,
+ hydrogen_env->parameter_count(),
+ argument_count_,
+ value_count,
+ outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue;
@@ -1013,14 +1020,14 @@
if (value->IsArgumentsObject()) {
op = NULL;
} else if (value->IsPushArgument()) {
- op = new LArgument(argument_index++);
+ op = new(zone()) LArgument(argument_index++);
} else {
op = UseAny(value);
}
result->AddValue(op, value->representation());
}
- if (!hydrogen_env->is_arguments_adaptor()) {
+ if (hydrogen_env->frame_type() == JS_FUNCTION) {
*argument_index_accumulator = argument_index;
}
@@ -1029,7 +1036,7 @@
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
- return new LGoto(instr->FirstSuccessor()->block_id());
+ return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
}
@@ -1039,10 +1046,10 @@
HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
- return new LGoto(successor->block_id());
+ return new(zone()) LGoto(successor->block_id());
}
- LBranch* result = new LBranch(UseRegister(value));
+ LBranch* result = new(zone()) LBranch(UseRegister(value));
// Tagged values that are not known smis or booleans require a
// deoptimization environment.
Representation rep = value->representation();
@@ -1058,24 +1065,25 @@
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister();
- return new LCmpMapAndBranch(value, temp);
+ return new(zone()) LCmpMapAndBranch(value, temp);
}
LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
- return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
+ return DefineAsRegister(
+ new(zone()) LArgumentsLength(UseRegister(length->value())));
}
LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
- return DefineAsRegister(new LArgumentsElements);
+ return DefineAsRegister(new(zone()) LArgumentsElements);
}
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LInstanceOf* result =
- new LInstanceOf(UseFixed(instr->left(), a0),
- UseFixed(instr->right(), a1));
+ new(zone()) LInstanceOf(UseFixed(instr->left(), a0),
+ UseFixed(instr->right(), a1));
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -1083,7 +1091,8 @@
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
HInstanceOfKnownGlobal* instr) {
LInstanceOfKnownGlobal* result =
- new LInstanceOfKnownGlobal(UseFixed(instr->left(), a0), FixedTemp(t0));
+ new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), a0),
+ FixedTemp(t0));
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -1093,10 +1102,10 @@
LOperand* receiver = UseFixed(instr->receiver(), a0);
LOperand* length = UseFixed(instr->length(), a2);
LOperand* elements = UseFixed(instr->elements(), a3);
- LApplyArguments* result = new LApplyArguments(function,
- receiver,
- length,
- elements);
+ LApplyArguments* result = new(zone()) LApplyArguments(function,
+ receiver,
+ length,
+ elements);
return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
}
@@ -1104,54 +1113,56 @@
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
++argument_count_;
LOperand* argument = Use(instr->argument());
- return new LPushArgument(argument);
+ return new(zone()) LPushArgument(argument);
}
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
+ return instr->HasNoUses()
+ ? NULL
+ : DefineAsRegister(new(zone()) LThisFunction);
}
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
+ return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
}
LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LOuterContext(context));
+ return DefineAsRegister(new(zone()) LOuterContext(context));
}
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
- return MarkAsCall(new LDeclareGlobals, instr);
+ return MarkAsCall(new(zone()) LDeclareGlobals, instr);
}
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGlobalObject(context));
+ return DefineAsRegister(new(zone()) LGlobalObject(context));
}
LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
LOperand* global_object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGlobalReceiver(global_object));
+ return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
}
LInstruction* LChunkBuilder::DoCallConstantFunction(
HCallConstantFunction* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallConstantFunction, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, v0), instr);
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* function = UseFixed(instr->function(), a1);
argument_count_ -= instr->argument_count();
- LInvokeFunction* result = new LInvokeFunction(function);
+ LInvokeFunction* result = new(zone()) LInvokeFunction(function);
return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
@@ -1160,19 +1171,19 @@
BuiltinFunctionId op = instr->op();
if (op == kMathLog || op == kMathSin || op == kMathCos) {
LOperand* input = UseFixedDouble(instr->value(), f4);
- LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL);
return MarkAsCall(DefineFixedDouble(result, f4), instr);
} else if (op == kMathPowHalf) {
// Input cannot be the same as the result.
// See lithium-codegen-mips.cc::DoMathPowHalf.
LOperand* input = UseFixedDouble(instr->value(), f8);
LOperand* temp = FixedTemp(f6);
- LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
return DefineFixedDouble(result, f4);
} else {
LOperand* input = UseRegisterAtStart(instr->value());
LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
- LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
switch (op) {
case kMathAbs:
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
@@ -1194,32 +1205,32 @@
ASSERT(instr->key()->representation().IsTagged());
argument_count_ -= instr->argument_count();
LOperand* key = UseFixed(instr->key(), a2);
- return MarkAsCall(DefineFixed(new LCallKeyed(key), v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), v0), instr);
}
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallNamed, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallNamed, v0), instr);
}
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallGlobal, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, v0), instr);
}
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallKnownGlobal, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, v0), instr);
}
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
LOperand* constructor = UseFixed(instr->constructor(), a1);
argument_count_ -= instr->argument_count();
- LCallNew* result = new LCallNew(constructor);
+ LCallNew* result = new(zone()) LCallNew(constructor);
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -1227,13 +1238,14 @@
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
LOperand* function = UseFixed(instr->function(), a1);
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallFunction(function), v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), v0),
+ instr);
}
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallRuntime, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, v0), instr);
}
@@ -1259,7 +1271,7 @@
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- return DefineAsRegister(new LBitI(left, right));
+ return DefineAsRegister(new(zone()) LBitI(left, right));
} else {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged());
@@ -1267,7 +1279,7 @@
LOperand* left = UseFixed(instr->left(), a1);
LOperand* right = UseFixed(instr->right(), a0);
- LArithmeticT* result = new LArithmeticT(instr->op(), left, right);
+ LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
return MarkAsCall(DefineFixed(result, v0), instr);
}
}
@@ -1276,7 +1288,8 @@
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ASSERT(instr->value()->representation().IsInteger32());
ASSERT(instr->representation().IsInteger32());
- return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value())));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return DefineAsRegister(new(zone()) LBitNotI(value));
}
@@ -1292,7 +1305,7 @@
LOperand* dividend = UseFixed(instr->left(), a0);
LOperand* divisor = UseFixed(instr->right(), a1);
return AssignEnvironment(AssignPointerMap(
- DefineFixed(new LDivI(dividend, divisor), v0)));
+ DefineFixed(new(zone()) LDivI(dividend, divisor), v0)));
} else {
return DoArithmeticT(Token::DIV, instr);
}
@@ -1308,15 +1321,15 @@
if (instr->HasPowerOf2Divisor()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
- mod = new LModI(value, UseOrConstant(instr->right()));
+ mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
} else {
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = UseRegister(instr->right());
- mod = new LModI(dividend,
- divisor,
- TempRegister(),
- FixedTemp(f20),
- FixedTemp(f22));
+ mod = new(zone()) LModI(dividend,
+ divisor,
+ TempRegister(),
+ FixedTemp(f20),
+ FixedTemp(f22));
}
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
@@ -1334,7 +1347,7 @@
// TODO(fschneider): Allow any register as input registers.
LOperand* left = UseFixedDouble(instr->left(), f2);
LOperand* right = UseFixedDouble(instr->right(), f4);
- LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
+ LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
return MarkAsCall(DefineFixedDouble(result, f2), instr);
}
}
@@ -1355,7 +1368,7 @@
} else {
left = UseRegisterAtStart(instr->LeastConstantOperand());
}
- LMulI* mul = new LMulI(left, right, temp);
+ LMulI* mul = new(zone()) LMulI(left, right, temp);
if (instr->CheckFlag(HValue::kCanOverflow) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
AssignEnvironment(mul);
@@ -1377,7 +1390,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
- LSubI* sub = new LSubI(left, right);
+ LSubI* sub = new(zone()) LSubI(left, right);
LInstruction* result = DefineAsRegister(sub);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
@@ -1397,7 +1410,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- LAddI* add = new LAddI(left, right);
+ LAddI* add = new(zone()) LAddI(left, right);
LInstruction* result = DefineAsRegister(add);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
@@ -1422,7 +1435,7 @@
LOperand* right = exponent_type.IsDouble() ?
UseFixedDouble(instr->right(), f4) :
UseFixed(instr->right(), a2);
- LPower* result = new LPower(left, right);
+ LPower* result = new(zone()) LPower(left, right);
return MarkAsCall(DefineFixedDouble(result, f0),
instr,
CAN_DEOPTIMIZE_EAGERLY);
@@ -1433,7 +1446,7 @@
ASSERT(instr->representation().IsDouble());
ASSERT(instr->global_object()->representation().IsTagged());
LOperand* global_object = UseFixed(instr->global_object(), a0);
- LRandom* result = new LRandom(global_object);
+ LRandom* result = new(zone()) LRandom(global_object);
return MarkAsCall(DefineFixedDouble(result, f0), instr);
}
@@ -1444,7 +1457,7 @@
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), a1);
LOperand* right = UseFixed(instr->right(), a0);
- LCmpT* result = new LCmpT(left, right);
+ LCmpT* result = new(zone()) LCmpT(left, right);
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -1457,14 +1470,14 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
- return new LCmpIDAndBranch(left, right);
+ return new(zone()) LCmpIDAndBranch(left, right);
} else {
ASSERT(r.IsDouble());
ASSERT(instr->left()->representation().IsDouble());
ASSERT(instr->right()->representation().IsDouble());
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return new LCmpIDAndBranch(left, right);
+ return new(zone()) LCmpIDAndBranch(left, right);
}
}
@@ -1473,47 +1486,50 @@
HCompareObjectEqAndBranch* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return new LCmpObjectEqAndBranch(left, right);
+ return new(zone()) LCmpObjectEqAndBranch(left, right);
}
LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
HCompareConstantEqAndBranch* instr) {
- return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value()));
+ return new(zone()) LCmpConstantEqAndBranch(
+ UseRegisterAtStart(instr->value()));
}
LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsNilAndBranch(UseRegisterAtStart(instr->value()));
+ return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
}
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
- return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()), temp);
+ return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()),
+ temp);
}
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
- return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp);
+ return new(zone()) LIsStringAndBranch(UseRegisterAtStart(instr->value()),
+ temp);
}
LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsSmiAndBranch(Use(instr->value()));
+ return new(zone()) LIsSmiAndBranch(Use(instr->value()));
}
LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
HIsUndetectableAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()),
- TempRegister());
+ return new(zone()) LIsUndetectableAndBranch(
+ UseRegisterAtStart(instr->value()), TempRegister());
}
@@ -1523,7 +1539,8 @@
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), a1);
LOperand* right = UseFixed(instr->right(), a0);
- LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right);
+ LStringCompareAndBranch* result =
+ new(zone()) LStringCompareAndBranch(left, right);
return MarkAsCall(result, instr);
}
@@ -1531,7 +1548,8 @@
LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
HHasInstanceTypeAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value()));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LHasInstanceTypeAndBranch(value);
}
@@ -1540,14 +1558,14 @@
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGetCachedArrayIndex(value));
+ return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
}
LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
HHasCachedArrayIndexAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LHasCachedArrayIndexAndBranch(
+ return new(zone()) LHasCachedArrayIndexAndBranch(
UseRegisterAtStart(instr->value()));
}
@@ -1555,40 +1573,41 @@
LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
HClassOfTestAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LClassOfTestAndBranch(UseRegister(instr->value()),
- TempRegister());
+ return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
+ TempRegister());
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LJSArrayLength(array));
+ return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LFixedArrayBaseLength(array));
+ return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
}
LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
LOperand* object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LElementsKind(object));
+ return DefineAsRegister(new(zone()) LElementsKind(object));
}
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value());
- LValueOf* result = new LValueOf(object, TempRegister());
+ LValueOf* result = new(zone()) LValueOf(object, TempRegister());
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
- UseRegister(instr->length())));
+ LOperand* value = UseRegisterAtStart(instr->index());
+ LOperand* length = UseRegister(instr->length());
+ return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
}
@@ -1601,7 +1620,7 @@
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
LOperand* value = UseFixed(instr->value(), a0);
- return MarkAsCall(new LThrow(value), instr);
+ return MarkAsCall(new(zone()) LThrow(value), instr);
}
@@ -1624,7 +1643,7 @@
if (from.IsTagged()) {
if (to.IsDouble()) {
LOperand* value = UseRegister(instr->value());
- LNumberUntagD* res = new LNumberUntagD(value);
+ LNumberUntagD* res = new(zone()) LNumberUntagD(value);
return AssignEnvironment(DefineAsRegister(res));
} else {
ASSERT(to.IsInteger32());
@@ -1632,14 +1651,17 @@
bool needs_check = !instr->value()->type().IsSmi();
LInstruction* res = NULL;
if (!needs_check) {
- res = DefineAsRegister(new LSmiUntag(value, needs_check));
+ res = DefineAsRegister(new(zone()) LSmiUntag(value, needs_check));
} else {
LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
: NULL;
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(f22)
: NULL;
- res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
+ res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
+ temp1,
+ temp2,
+ temp3));
res = AssignEnvironment(res);
}
return res;
@@ -1653,16 +1675,15 @@
// Make sure that the temp and result_temp registers are
// different.
LUnallocated* result_temp = TempRegister();
- LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
+ LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
Define(result, result_temp);
return AssignPointerMap(result);
} else {
ASSERT(to.IsInteger32());
LOperand* value = UseRegister(instr->value());
- LDoubleToI* res =
- new LDoubleToI(value,
- TempRegister(),
- instr->CanTruncateToInt32() ? TempRegister() : NULL);
+ LOperand* temp1 = TempRegister();
+ LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
+ LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
return AssignEnvironment(DefineAsRegister(res));
}
} else if (from.IsInteger32()) {
@@ -1670,15 +1691,15 @@
HValue* val = instr->value();
LOperand* value = UseRegisterAtStart(val);
if (val->HasRange() && val->range()->IsInSmiRange()) {
- return DefineAsRegister(new LSmiTag(value));
+ return DefineAsRegister(new(zone()) LSmiTag(value));
} else {
- LNumberTagI* result = new LNumberTagI(value);
+ LNumberTagI* result = new(zone()) LNumberTagI(value);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
}
} else {
ASSERT(to.IsDouble());
LOperand* value = Use(instr->value());
- return DefineAsRegister(new LInteger32ToDouble(value));
+ return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
}
}
UNREACHABLE();
@@ -1688,13 +1709,13 @@
LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckNonSmi(value));
+ return AssignEnvironment(new(zone()) LCheckNonSmi(value));
}
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- LInstruction* result = new LCheckInstanceType(value);
+ LInstruction* result = new(zone()) LCheckInstanceType(value);
return AssignEnvironment(result);
}
@@ -1702,26 +1723,26 @@
LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
- LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
+ LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
return AssignEnvironment(result);
}
LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckSmi(value));
+ return AssignEnvironment(new(zone()) LCheckSmi(value));
}
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckFunction(value));
+ return AssignEnvironment(new(zone()) LCheckFunction(value));
}
LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- LInstruction* result = new LCheckMap(value);
+ LInstruction* result = new(zone()) LCheckMap(value);
return AssignEnvironment(result);
}
@@ -1732,14 +1753,14 @@
LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) {
// Revisit this decision, here and 8 lines below.
- return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(f22)));
+ return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(f22)));
} else if (input_rep.IsInteger32()) {
- return DefineAsRegister(new LClampIToUint8(reg));
+ return DefineAsRegister(new(zone()) LClampIToUint8(reg));
} else {
ASSERT(input_rep.IsTagged());
// Register allocator doesn't (yet) support allocation of double
// temps. Reserve f22 explicitly.
- LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(f22));
+ LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(f22));
return AssignEnvironment(DefineAsRegister(result));
}
}
@@ -1752,7 +1773,7 @@
if (input_rep.IsDouble()) {
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
- LDoubleToI* res = new LDoubleToI(reg, temp1, temp2);
+ LDoubleToI* res = new(zone()) LDoubleToI(reg, temp1, temp2);
return AssignEnvironment(DefineAsRegister(res));
} else if (input_rep.IsInteger32()) {
// Canonicalization should already have removed the hydrogen instruction in
@@ -1764,25 +1785,25 @@
LOperand* temp1 = TempRegister();
LOperand* temp2 = TempRegister();
LOperand* temp3 = FixedTemp(f22);
- LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
+ LTaggedToI* res = new(zone()) LTaggedToI(reg, temp1, temp2, temp3);
return AssignEnvironment(DefineSameAsFirst(res));
}
}
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
- return new LReturn(UseFixed(instr->value(), v0));
+ return new(zone()) LReturn(UseFixed(instr->value(), v0));
}
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
Representation r = instr->representation();
if (r.IsInteger32()) {
- return DefineAsRegister(new LConstantI);
+ return DefineAsRegister(new(zone()) LConstantI);
} else if (r.IsDouble()) {
- return DefineAsRegister(new LConstantD);
+ return DefineAsRegister(new(zone()) LConstantD);
} else if (r.IsTagged()) {
- return DefineAsRegister(new LConstantT);
+ return DefineAsRegister(new(zone()) LConstantT);
} else {
UNREACHABLE();
return NULL;
@@ -1791,7 +1812,7 @@
LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
- LLoadGlobalCell* result = new LLoadGlobalCell;
+ LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
return instr->RequiresHoleCheck()
? AssignEnvironment(DefineAsRegister(result))
: DefineAsRegister(result);
@@ -1800,7 +1821,7 @@
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* global_object = UseFixed(instr->global_object(), a0);
- LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
+ LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -1810,8 +1831,8 @@
// Use a temp to check the value in the cell in the case where we perform
// a hole check.
return instr->RequiresHoleCheck()
- ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister()))
- : new LStoreGlobalCell(value, NULL);
+ ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
+ : new(zone()) LStoreGlobalCell(value, NULL);
}
@@ -1819,14 +1840,15 @@
LOperand* global_object = UseFixed(instr->global_object(), a1);
LOperand* value = UseFixed(instr->value(), a0);
LStoreGlobalGeneric* result =
- new LStoreGlobalGeneric(global_object, value);
+ new(zone()) LStoreGlobalGeneric(global_object, value);
return MarkAsCall(result, instr);
}
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- LInstruction* result = DefineAsRegister(new LLoadContextSlot(context));
+ LInstruction* result =
+ DefineAsRegister(new(zone()) LLoadContextSlot(context));
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
}
@@ -1841,14 +1863,14 @@
context = UseRegister(instr->context());
value = UseRegister(instr->value());
}
- LInstruction* result = new LStoreContextSlot(context, value);
+ LInstruction* result = new(zone()) LStoreContextSlot(context, value);
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
}
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
return DefineAsRegister(
- new LLoadNamedField(UseRegisterAtStart(instr->object())));
+ new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
}
@@ -1857,11 +1879,13 @@
ASSERT(instr->representation().IsTagged());
if (instr->need_generic()) {
LOperand* obj = UseFixed(instr->object(), a0);
- LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
return MarkAsCall(DefineFixed(result, v0), instr);
} else {
LOperand* obj = UseRegisterAtStart(instr->object());
- LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
return AssignEnvironment(DefineAsRegister(result));
}
}
@@ -1869,7 +1893,7 @@
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), a0);
- LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), v0);
+ LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), v0);
return MarkAsCall(result, instr);
}
@@ -1877,20 +1901,20 @@
LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
HLoadFunctionPrototype* instr) {
return AssignEnvironment(DefineAsRegister(
- new LLoadFunctionPrototype(UseRegister(instr->function()))));
+ new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
}
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadElements(input));
+ return DefineAsRegister(new(zone()) LLoadElements(input));
}
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
HLoadExternalArrayPointer* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadExternalArrayPointer(input));
+ return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
}
@@ -1900,7 +1924,7 @@
ASSERT(instr->key()->representation().IsInteger32());
LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterAtStart(instr->key());
- LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
+ LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
if (instr->RequiresHoleCheck()) AssignEnvironment(result);
return DefineAsRegister(result);
}
@@ -1913,7 +1937,7 @@
LOperand* elements = UseTempRegister(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
- new LLoadKeyedFastDoubleElement(elements, key);
+ new(zone()) LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
@@ -1933,7 +1957,7 @@
LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key());
LLoadKeyedSpecializedArrayElement* result =
- new LLoadKeyedSpecializedArrayElement(external_pointer, key);
+ new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
@@ -1947,7 +1971,7 @@
LOperand* key = UseFixed(instr->key(), a0);
LInstruction* result =
- DefineFixed(new LLoadKeyedGeneric(object, key), v0);
+ DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0);
return MarkAsCall(result, instr);
}
@@ -1966,7 +1990,7 @@
LOperand* key = needs_write_barrier
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
- return new LStoreKeyedFastElement(obj, key, val);
+ return new(zone()) LStoreKeyedFastElement(obj, key, val);
}
@@ -1980,7 +2004,7 @@
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- return new LStoreKeyedFastDoubleElement(elements, key, val);
+ return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
}
@@ -2007,9 +2031,9 @@
: UseRegister(instr->value());
LOperand* key = UseRegisterOrConstant(instr->key());
- return new LStoreKeyedSpecializedArrayElement(external_pointer,
- key,
- val);
+ return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
+ key,
+ val);
}
@@ -2022,7 +2046,7 @@
ASSERT(instr->key()->representation().IsTagged());
ASSERT(instr->value()->representation().IsTagged());
- return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
+ return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
}
@@ -2033,14 +2057,16 @@
LOperand* object = UseRegister(instr->object());
LOperand* new_map_reg = TempRegister();
LTransitionElementsKind* result =
- new LTransitionElementsKind(object, new_map_reg, NULL);
+ new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
return DefineSameAsFirst(result);
} else {
LOperand* object = UseFixed(instr->object(), a0);
LOperand* fixed_object_reg = FixedTemp(a2);
LOperand* new_map_reg = FixedTemp(a3);
LTransitionElementsKind* result =
- new LTransitionElementsKind(object, new_map_reg, fixed_object_reg);
+ new(zone()) LTransitionElementsKind(object,
+ new_map_reg,
+ fixed_object_reg);
return MarkAsCall(DefineFixed(result, v0), instr);
}
}
@@ -2057,7 +2083,7 @@
? UseTempRegister(instr->value())
: UseRegister(instr->value());
- return new LStoreNamedField(obj, val);
+ return new(zone()) LStoreNamedField(obj, val);
}
@@ -2065,7 +2091,7 @@
LOperand* obj = UseFixed(instr->object(), a1);
LOperand* val = UseFixed(instr->value(), a0);
- LInstruction* result = new LStoreNamedGeneric(obj, val);
+ LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
return MarkAsCall(result, instr);
}
@@ -2073,66 +2099,67 @@
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return MarkAsCall(DefineFixed(new LStringAdd(left, right), v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), v0),
+ instr);
}
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
LOperand* string = UseTempRegister(instr->string());
LOperand* index = UseTempRegister(instr->index());
- LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
+ LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
}
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
LOperand* char_code = UseRegister(instr->value());
- LStringCharFromCode* result = new LStringCharFromCode(char_code);
+ LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
return AssignPointerMap(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LStringLength(string));
+ return DefineAsRegister(new(zone()) LStringLength(string));
}
LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
- LAllocateObject* result = new LAllocateObject();
+ LAllocateObject* result = new(zone()) LAllocateObject();
return AssignPointerMap(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
- return MarkAsCall(DefineFixed(new LFastLiteral, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, v0), instr);
}
LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
- return MarkAsCall(DefineFixed(new LArrayLiteral, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, v0), instr);
}
LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
- return MarkAsCall(DefineFixed(new LObjectLiteral, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, v0), instr);
}
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
- return MarkAsCall(DefineFixed(new LRegExpLiteral, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, v0), instr);
}
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
- return MarkAsCall(DefineFixed(new LFunctionLiteral, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, v0), instr);
}
LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
LOperand* object = UseFixed(instr->object(), a0);
LOperand* key = UseFixed(instr->key(), a1);
- LDeleteProperty* result = new LDeleteProperty(object, key);
+ LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
return MarkAsCall(DefineFixed(result, v0), instr);
}
@@ -2140,13 +2167,13 @@
LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
allocator_->MarkAsOsrEntry();
current_block_->last_environment()->set_ast_id(instr->ast_id());
- return AssignEnvironment(new LOsrEntry);
+ return AssignEnvironment(new(zone()) LOsrEntry);
}
LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
int spill_index = chunk()->GetParameterStackSlot(instr->index());
- return DefineAsSpilled(new LParameter, spill_index);
+ return DefineAsSpilled(new(zone()) LParameter, spill_index);
}
@@ -2156,13 +2183,13 @@
Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
- return DefineAsSpilled(new LUnknownOSRValue, spill_index);
+ return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
}
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallStub, v0), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallStub, v0), instr);
}
@@ -2179,32 +2206,33 @@
LOperand* arguments = UseRegister(instr->arguments());
LOperand* length = UseTempRegister(instr->length());
LOperand* index = UseRegister(instr->index());
- LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
+ LAccessArgumentsAt* result =
+ new(zone()) LAccessArgumentsAt(arguments, length, index);
return AssignEnvironment(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
LOperand* object = UseFixed(instr->value(), a0);
- LToFastProperties* result = new LToFastProperties(object);
+ LToFastProperties* result = new(zone()) LToFastProperties(object);
return MarkAsCall(DefineFixed(result, v0), instr);
}
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
- LTypeof* result = new LTypeof(UseFixed(instr->value(), a0));
+ LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), a0));
return MarkAsCall(DefineFixed(result, v0), instr);
}
LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
- return new LTypeofIsAndBranch(UseTempRegister(instr->value()));
+ return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
}
LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
HIsConstructCallAndBranch* instr) {
- return new LIsConstructCallAndBranch(TempRegister());
+ return new(zone()) LIsConstructCallAndBranch(TempRegister());
}
@@ -2227,7 +2255,7 @@
// 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()) {
- LInstruction* result = new LLazyBailout;
+ LInstruction* result = new(zone()) LLazyBailout;
result = AssignEnvironment(result);
instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
@@ -2241,10 +2269,10 @@
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
if (instr->is_function_entry()) {
- return MarkAsCall(new LStackCheck, instr);
+ return MarkAsCall(new(zone()) LStackCheck, instr);
} else {
ASSERT(instr->is_backwards_branch());
- return AssignEnvironment(AssignPointerMap(new LStackCheck));
+ return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
}
}
@@ -2256,7 +2284,8 @@
instr->arguments_count(),
instr->function(),
undefined,
- instr->call_kind());
+ instr->call_kind(),
+ instr->is_construct());
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedClosure(instr->closure());
return NULL;
@@ -2274,9 +2303,37 @@
LInstruction* LChunkBuilder::DoIn(HIn* instr) {
LOperand* key = UseRegisterAtStart(instr->key());
LOperand* object = UseRegisterAtStart(instr->object());
- LIn* result = new LIn(key, object);
+ LIn* result = new(zone()) LIn(key, object);
return MarkAsCall(DefineFixed(result, v0), instr);
}
+LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
+ LOperand* object = UseFixed(instr->enumerable(), a0);
+ LForInPrepareMap* result = new LForInPrepareMap(object);
+ return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
+}
+
+
+LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
+ LOperand* map = UseRegister(instr->map());
+ return AssignEnvironment(DefineAsRegister(
+ new LForInCacheArray(map)));
+}
+
+
+LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
+ LOperand* value = UseRegisterAtStart(instr->value());
+ LOperand* map = UseRegisterAtStart(instr->map());
+ return AssignEnvironment(new LCheckMapValue(value, map));
+}
+
+
+LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
+ LOperand* object = UseRegister(instr->object());
+ LOperand* index = UseRegister(instr->index());
+ return DefineAsRegister(new LLoadFieldByIndex(object, index));
+}
+
+
} } // namespace v8::internal
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index f41689e..cc9d3b1 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -173,7 +173,11 @@
V(TypeofIsAndBranch) \
V(UnaryMathOperation) \
V(UnknownOSRValue) \
- V(ValueOf)
+ V(ValueOf) \
+ V(ForInPrepareMap) \
+ V(ForInCacheArray) \
+ V(CheckMapValue) \
+ V(LoadFieldByIndex)
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
@@ -2072,6 +2076,62 @@
};
+class LForInPrepareMap: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LForInPrepareMap(LOperand* object) {
+ inputs_[0] = object;
+ }
+
+ LOperand* object() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(ForInPrepareMap, "for-in-prepare-map")
+};
+
+
+class LForInCacheArray: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LForInCacheArray(LOperand* map) {
+ inputs_[0] = map;
+ }
+
+ LOperand* map() { return inputs_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")
+
+ int idx() {
+ return HForInCacheArray::cast(this->hydrogen_value())->idx();
+ }
+};
+
+
+class LCheckMapValue: public LTemplateInstruction<0, 2, 0> {
+ public:
+ LCheckMapValue(LOperand* value, LOperand* map) {
+ inputs_[0] = value;
+ inputs_[1] = map;
+ }
+
+ LOperand* value() { return inputs_[0]; }
+ LOperand* map() { return inputs_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(CheckMapValue, "check-map-value")
+};
+
+
+class LLoadFieldByIndex: public LTemplateInstruction<1, 2, 0> {
+ public:
+ LLoadFieldByIndex(LOperand* object, LOperand* index) {
+ inputs_[0] = object;
+ inputs_[1] = index;
+ }
+
+ LOperand* object() { return inputs_[0]; }
+ LOperand* index() { return inputs_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex, "load-field-by-index")
+};
+
+
class LChunkBuilder;
class LChunk: public ZoneObject {
public:
@@ -2139,6 +2199,7 @@
: chunk_(NULL),
info_(info),
graph_(graph),
+ zone_(graph->isolate()->zone()),
status_(UNUSED),
current_instruction_(NULL),
current_block_(NULL),
@@ -2168,6 +2229,7 @@
LChunk* chunk() const { return chunk_; }
CompilationInfo* info() const { return info_; }
HGraph* graph() const { return graph_; }
+ Zone* zone() const { return zone_; }
bool is_unused() const { return status_ == UNUSED; }
bool is_building() const { return status_ == BUILDING; }
@@ -2273,6 +2335,7 @@
LChunk* chunk_;
CompilationInfo* info_;
HGraph* const graph_;
+ Zone* zone_;
Status status_;
HInstruction* current_instruction_;
HBasicBlock* current_block_;
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 7a733bc..77d03b5 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -5093,6 +5093,48 @@
}
+void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
+ Label next;
+ // Preload a couple of values used in the loop.
+ Register empty_fixed_array_value = t2;
+ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
+ Register empty_descriptor_array_value = t3;
+ LoadRoot(empty_descriptor_array_value,
+ Heap::kEmptyDescriptorArrayRootIndex);
+ mov(a1, a0);
+ bind(&next);
+
+ // Check that there are no elements. Register a1 contains the
+ // current JS object we've reached through the prototype chain.
+ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
+ Branch(call_runtime, ne, a2, Operand(empty_fixed_array_value));
+
+ // Check that instance descriptors are not empty so that we can
+ // check for an enum cache. Leave the map in a2 for the subsequent
+ // prototype load.
+ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
+ lw(a3, FieldMemOperand(a2, Map::kInstanceDescriptorsOrBitField3Offset));
+ JumpIfSmi(a3, call_runtime);
+
+ // Check that there is an enum cache in the non-empty instance
+ // descriptors (a3). This is the case if the next enumeration
+ // index field does not contain a smi.
+ lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumerationIndexOffset));
+ JumpIfSmi(a3, call_runtime);
+
+ // For all objects but the receiver, check that the cache is empty.
+ Label check_prototype;
+ Branch(&check_prototype, eq, a1, Operand(a0));
+ lw(a3, FieldMemOperand(a3, DescriptorArray::kEnumCacheBridgeCacheOffset));
+ Branch(call_runtime, ne, a3, Operand(empty_fixed_array_value));
+
+ // Load the prototype from the map and loop if non-null.
+ bind(&check_prototype);
+ lw(a1, FieldMemOperand(a2, Map::kPrototypeOffset));
+ Branch(&next, ne, a1, Operand(null_value));
+}
+
+
void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
ASSERT(!output_reg.is(input_reg));
Label done;
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 56a3433..6ae8657 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -1353,6 +1353,10 @@
Register value,
Register scratch);
+ // Expects object in a0 and returns map with validated enum cache
+ // in a0. Assumes that any other register can be used as a scratch.
+ void CheckEnumCache(Register null_value, Label* call_runtime);
+
private:
void CallCFunctionHelper(Register function,
int num_reg_arguments,
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
index cb210fe..330ff2b 100644
--- a/src/mips/regexp-macro-assembler-mips.cc
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -1056,7 +1056,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt();
+ MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid.
int delta = code_handle->address() - re_code->address();
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 176be9b..bc6217b 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1988,8 +1988,7 @@
bool DescriptorArray::IsProperty(int descriptor_number) {
- Entry entry(this, descriptor_number);
- return IsPropertyDescriptor(&entry);
+ return IsRealProperty(GetType(descriptor_number));
}
diff --git a/src/objects.cc b/src/objects.cc
index 538986d..bc0a82e 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -6862,10 +6862,21 @@
// Left hand side is longer. Recurse over right.
if (to > boundary) {
String* second = cons_string->second();
- WriteToFlat(second,
- sink + boundary - from,
- 0,
+ // When repeatedly appending to a string, we get a cons string that
+ // is unbalanced to the left, a list, essentially. We inline the
+ // common case of sequential ascii right child.
+ if (to - boundary == 1) {
+ sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
+ } else if (second->IsSeqAsciiString()) {
+ CopyChars(sink + boundary - from,
+ SeqAsciiString::cast(second)->GetChars(),
to - boundary);
+ } else {
+ WriteToFlat(second,
+ sink + boundary - from,
+ 0,
+ to - boundary);
+ }
to = boundary;
}
source = first;
diff --git a/src/objects.h b/src/objects.h
index 4e02d6f..be75fab 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2589,20 +2589,6 @@
static const int kMaxNumberOfDescriptors = 1024 + 512;
private:
- // An entry in a DescriptorArray, represented as an (array, index) pair.
- class Entry {
- public:
- inline explicit Entry(DescriptorArray* descs, int index) :
- descs_(descs), index_(index) { }
-
- inline PropertyType type() { return descs_->GetType(index_); }
- inline Object* GetCallbackObject() { return descs_->GetValue(index_); }
-
- private:
- DescriptorArray* descs_;
- int index_;
- };
-
// Conversion from descriptor number to array indices.
static int ToKeyIndex(int descriptor_number) {
return descriptor_number+kFirstIndex;
@@ -7933,10 +7919,6 @@
}
}
- bool ContainsAccessor() {
- return IsJSAccessor(getter()) || IsJSAccessor(setter());
- }
-
#ifdef OBJECT_PRINT
void AccessorPairPrint(FILE* out = stdout);
#endif
@@ -7949,15 +7931,6 @@
static const int kSize = kSetterOffset + kPointerSize;
private:
- // Strangely enough, in addition to functions and harmony proxies, the spec
- // requires us to consider undefined as a kind of accessor, too:
- // var obj = {};
- // Object.defineProperty(obj, "foo", {get: undefined});
- // assertTrue("foo" in obj);
- bool IsJSAccessor(Object* obj) {
- return obj->IsSpecFunction() || obj->IsUndefined();
- }
-
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair);
};
diff --git a/src/parser.cc b/src/parser.cc
index f0556cb..5f04cab 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1184,10 +1184,10 @@
switch (peek()) {
case Token::FUNCTION:
- return ParseFunctionDeclaration(ok);
+ return ParseFunctionDeclaration(NULL, ok);
case Token::LET:
case Token::CONST:
- return ParseVariableStatement(kModuleElement, ok);
+ return ParseVariableStatement(kModuleElement, NULL, ok);
case Token::IMPORT:
return ParseImportDeclaration(ok);
case Token::EXPORT:
@@ -1205,7 +1205,7 @@
estmt->expression()->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_symbol()) &&
!scanner().literal_contains_escapes()) {
- return ParseModuleDeclaration(ok);
+ return ParseModuleDeclaration(NULL, ok);
}
}
return stmt;
@@ -1214,20 +1214,22 @@
}
-Block* Parser::ParseModuleDeclaration(bool* ok) {
+Block* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
// ModuleDeclaration:
// 'module' Identifier Module
// Create new block with one expected declaration.
Block* block = factory()->NewBlock(NULL, 1, true);
Handle<String> name = ParseIdentifier(CHECK_OK);
- // top_scope_->AddDeclaration(
- // factory()->NewModuleDeclaration(proxy, module, top_scope_));
- VariableProxy* proxy = Declare(name, LET, NULL, true, CHECK_OK);
- Module* module = ParseModule(ok);
+ Module* module = ParseModule(CHECK_OK);
+ VariableProxy* proxy = NewUnresolved(name, LET);
+ Declaration* declaration =
+ factory()->NewModuleDeclaration(proxy, module, top_scope_);
+ Declare(declaration, true, CHECK_OK);
+
// TODO(rossberg): Add initialization statement to block.
- USE(proxy);
- USE(module);
+
+ if (names) names->Add(name);
return block;
}
@@ -1235,19 +1237,26 @@
Module* Parser::ParseModule(bool* ok) {
// Module:
// '{' ModuleElement '}'
- // '=' ModulePath
- // 'at' String
+ // '=' ModulePath ';'
+ // 'at' String ';'
switch (peek()) {
case Token::LBRACE:
return ParseModuleLiteral(ok);
- case Token::ASSIGN:
+ case Token::ASSIGN: {
Expect(Token::ASSIGN, CHECK_OK);
- return ParseModulePath(ok);
+ Module* result = ParseModulePath(CHECK_OK);
+ ExpectSemicolon(CHECK_OK);
+ return result;
+ }
- default:
- return ParseModuleUrl(ok);
+ default: {
+ ExpectContextualKeyword("at", CHECK_OK);
+ Module* result = ParseModuleUrl(CHECK_OK);
+ ExpectSemicolon(CHECK_OK);
+ return result;
+ }
}
}
@@ -1316,31 +1325,122 @@
Module* Parser::ParseModuleUrl(bool* ok) {
// Module:
- // 'at' String
+ // String
- Expect(Token::IDENTIFIER, CHECK_OK);
- Handle<String> symbol = GetSymbol(CHECK_OK);
- if (!symbol->IsEqualTo(CStrVector("at"))) {
- *ok = false;
- ReportUnexpectedToken(scanner().current_token());
- return NULL;
- }
Expect(Token::STRING, CHECK_OK);
- symbol = GetSymbol(CHECK_OK);
+ Handle<String> symbol = GetSymbol(CHECK_OK);
return factory()->NewModuleUrl(symbol);
}
-Block* Parser::ParseImportDeclaration(bool* ok) {
- // TODO(rossberg)
- return NULL;
+Module* Parser::ParseModuleSpecifier(bool* ok) {
+ // ModuleSpecifier:
+ // String
+ // ModulePath
+
+ if (peek() == Token::STRING) {
+ return ParseModuleUrl(ok);
+ } else {
+ return ParseModulePath(ok);
+ }
}
-Block* Parser::ParseExportDeclaration(bool* ok) {
- // TODO(rossberg)
- return NULL;
+Block* Parser::ParseImportDeclaration(bool* ok) {
+ // ImportDeclaration:
+ // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
+ //
+ // TODO(ES6): implement destructuring ImportSpecifiers
+
+ Expect(Token::IMPORT, CHECK_OK);
+ ZoneStringList names(1);
+
+ Handle<String> name = ParseIdentifierName(CHECK_OK);
+ while (peek() == Token::COMMA) {
+ Consume(Token::COMMA);
+ name = ParseIdentifierName(CHECK_OK);
+ names.Add(name);
+ }
+
+ ExpectContextualKeyword("from", CHECK_OK);
+ Module* module = ParseModuleSpecifier(CHECK_OK);
+ ExpectSemicolon(CHECK_OK);
+
+ // Generate a separate declaration for each identifier.
+ // TODO(ES6): once we implement destructuring, make that one declaration.
+ Block* block = factory()->NewBlock(NULL, 1, true);
+ for (int i = 0; i < names.length(); ++i) {
+ VariableProxy* proxy = NewUnresolved(names[i], LET);
+ Declaration* declaration =
+ factory()->NewImportDeclaration(proxy, module, top_scope_);
+ Declare(declaration, true, CHECK_OK);
+ // TODO(rossberg): Add initialization statement to block.
+ }
+
+
+ return block;
+}
+
+
+Statement* Parser::ParseExportDeclaration(bool* ok) {
+ // ExportDeclaration:
+ // 'export' Identifier (',' Identifier)* ';'
+ // 'export' VariableDeclaration
+ // 'export' FunctionDeclaration
+ // 'export' ModuleDeclaration
+ //
+ // TODO(ES6): implement structuring ExportSpecifiers
+
+ Expect(Token::EXPORT, CHECK_OK);
+
+ Statement* result = NULL;
+ ZoneStringList names(1);
+ switch (peek()) {
+ case Token::IDENTIFIER: {
+ Handle<String> name = ParseIdentifier(CHECK_OK);
+ // Handle 'module' as a context-sensitive keyword.
+ if (!name->IsEqualTo(CStrVector("module"))) {
+ names.Add(name);
+ while (peek() == Token::COMMA) {
+ Consume(Token::COMMA);
+ name = ParseIdentifier(CHECK_OK);
+ names.Add(name);
+ }
+ ExpectSemicolon(CHECK_OK);
+ result = factory()->NewEmptyStatement();
+ } else {
+ result = ParseModuleDeclaration(&names, CHECK_OK);
+ }
+ break;
+ }
+
+ case Token::FUNCTION:
+ result = ParseFunctionDeclaration(&names, CHECK_OK);
+ break;
+
+ case Token::VAR:
+ case Token::LET:
+ case Token::CONST:
+ result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
+ break;
+
+ default:
+ *ok = false;
+ ReportUnexpectedToken(scanner().current_token());
+ return NULL;
+ }
+
+ // Extract declared names into export declarations.
+ for (int i = 0; i < names.length(); ++i) {
+ VariableProxy* proxy = NewUnresolved(names[i], LET);
+ Declaration* declaration =
+ factory()->NewExportDeclaration(proxy, top_scope_);
+ top_scope_->AddDeclaration(declaration);
+ }
+
+ ASSERT(result != NULL);
+ return result;
}
@@ -1358,10 +1458,10 @@
switch (peek()) {
case Token::FUNCTION:
- return ParseFunctionDeclaration(ok);
+ return ParseFunctionDeclaration(NULL, ok);
case Token::LET:
case Token::CONST:
- return ParseVariableStatement(kModuleElement, ok);
+ return ParseVariableStatement(kModuleElement, NULL, ok);
default:
return ParseStatement(labels, ok);
}
@@ -1403,7 +1503,7 @@
case Token::CONST: // fall through
case Token::LET:
case Token::VAR:
- stmt = ParseVariableStatement(kStatement, ok);
+ stmt = ParseVariableStatement(kStatement, NULL, ok);
break;
case Token::SEMICOLON:
@@ -1480,7 +1580,7 @@
*ok = false;
return NULL;
}
- return ParseFunctionDeclaration(ok);
+ return ParseFunctionDeclaration(NULL, ok);
}
case Token::DEBUGGER:
@@ -1497,21 +1597,22 @@
}
-VariableProxy* Parser::Declare(Handle<String> name,
- VariableMode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok) {
- Variable* var = NULL;
+VariableProxy* Parser::NewUnresolved(Handle<String> name, VariableMode mode) {
// If we are inside a function, a declaration of a var/const variable is a
// truly local variable, and the scope of the variable is always the function
// scope.
// Let/const variables in harmony mode are always added to the immediately
// enclosing scope.
- Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
- ? top_scope_ : top_scope_->DeclarationScope();
- InitializationFlag init_flag = (fun != NULL || mode == VAR)
- ? kCreatedInitialized : kNeedsInitialization;
+ return DeclarationScope(mode)->NewUnresolved(
+ factory(), name, scanner().location().beg_pos);
+}
+
+
+void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
+ Handle<String> name = declaration->proxy()->name();
+ VariableMode mode = declaration->mode();
+ Scope* declaration_scope = DeclarationScope(mode);
+ Variable* var = NULL;
// If a function scope exists, then we can statically declare this
// variable and also set its mode. In any case, a Declaration node
@@ -1531,7 +1632,8 @@
var = declaration_scope->LocalLookup(name);
if (var == NULL) {
// Declare the name.
- var = declaration_scope->DeclareLocal(name, mode, init_flag);
+ var = declaration_scope->DeclareLocal(
+ name, mode, declaration->initialization());
} else {
// The name was declared in this scope before; check for conflicting
// re-declarations. We have a conflict if either of the declarations is
@@ -1558,7 +1660,7 @@
Vector<const char*> args(elms, 2);
ReportMessage("redeclaration", args);
*ok = false;
- return NULL;
+ return;
}
const char* type = (var->mode() == VAR)
? "var" : var->is_const_mode() ? "const" : "let";
@@ -1588,10 +1690,7 @@
// semantic issue as long as we keep the source order, but it may be
// a performance issue since it may lead to repeated
// Runtime::DeclareContextSlot() calls.
- VariableProxy* proxy = declaration_scope->NewUnresolved(
- factory(), name, scanner().location().beg_pos);
- declaration_scope->AddDeclaration(
- factory()->NewVariableDeclaration(proxy, mode, fun, top_scope_));
+ declaration_scope->AddDeclaration(declaration);
if ((mode == CONST || mode == CONST_HARMONY) &&
declaration_scope->is_global_scope()) {
@@ -1615,7 +1714,7 @@
mode,
true,
kind,
- init_flag);
+ declaration->initialization());
var->AllocateTo(Variable::LOOKUP, -1);
resolve = true;
}
@@ -1644,9 +1743,7 @@
// initialization code. Thus, inside the 'with' statement, we need
// both access to the static and the dynamic context chain; the
// runtime needs to provide both.
- if (resolve && var != NULL) proxy->BindTo(var);
-
- return proxy;
+ if (resolve && var != NULL) declaration->proxy()->BindTo(var);
}
@@ -1673,7 +1770,7 @@
// isn't lazily compiled. The extension structures are only
// accessible while parsing the first time not when reparsing
// because of lazy compilation.
- top_scope_->DeclarationScope()->ForceEagerCompilation();
+ DeclarationScope(VAR)->ForceEagerCompilation();
// Compute the function template for the native function.
v8::Handle<v8::FunctionTemplate> fun_template =
@@ -1698,16 +1795,19 @@
// TODO(1240846): It's weird that native function declarations are
// introduced dynamically when we meet their declarations, whereas
// other functions are set up when entering the surrounding scope.
+ VariableProxy* proxy = NewUnresolved(name, VAR);
+ Declaration* declaration =
+ factory()->NewVariableDeclaration(proxy, VAR, top_scope_);
+ Declare(declaration, true, CHECK_OK);
SharedFunctionInfoLiteral* lit =
factory()->NewSharedFunctionInfoLiteral(shared);
- VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
return factory()->NewExpressionStatement(
factory()->NewAssignment(
- Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+ Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition));
}
-Statement* Parser::ParseFunctionDeclaration(bool* ok) {
+Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK);
@@ -1724,7 +1824,11 @@
// scope, we treat is as such and introduce the function with it's
// initial value upon entering the corresponding scope.
VariableMode mode = is_extended_mode() ? LET : VAR;
- Declare(name, mode, fun, true, CHECK_OK);
+ VariableProxy* proxy = NewUnresolved(name, mode);
+ Declaration* declaration =
+ factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
+ Declare(declaration, true, CHECK_OK);
+ if (names) names->Add(name);
return factory()->NewEmptyStatement();
}
@@ -1791,13 +1895,14 @@
Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
+ ZoneStringList* names,
bool* ok) {
// VariableStatement ::
// VariableDeclarations ';'
Handle<String> ignore;
Block* result =
- ParseVariableDeclarations(var_context, NULL, &ignore, CHECK_OK);
+ ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return result;
}
@@ -1817,6 +1922,7 @@
Block* Parser::ParseVariableDeclarations(
VariableDeclarationContext var_context,
VariableDeclarationProperties* decl_props,
+ ZoneStringList* names,
Handle<String>* out,
bool* ok) {
// VariableDeclarations ::
@@ -1902,8 +2008,8 @@
UNREACHABLE(); // by current callers
}
- Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
- ? top_scope_ : top_scope_->DeclarationScope();
+ Scope* declaration_scope = DeclarationScope(mode);
+
// The scope of a var/const declared variable anywhere inside a function
// is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
// transform a source-level var/const declaration into a (Function)
@@ -1950,7 +2056,10 @@
// For let/const declarations in harmony mode, we can also immediately
// pre-resolve the proxy because it resides in the same scope as the
// declaration.
- VariableProxy* proxy = Declare(name, mode, NULL, mode != VAR, CHECK_OK);
+ VariableProxy* proxy = NewUnresolved(name, mode);
+ Declaration* declaration =
+ factory()->NewVariableDeclaration(proxy, mode, top_scope_);
+ Declare(declaration, mode != VAR, CHECK_OK);
nvars++;
if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
ReportMessageAt(scanner().location(), "too_many_variables",
@@ -1958,6 +2067,7 @@
*ok = false;
return NULL;
}
+ if (names) names->Add(name);
// Parse initialization expression if present and/or needed. A
// declaration of the form:
@@ -2610,7 +2720,7 @@
if (peek() == Token::VAR || peek() == Token::CONST) {
Handle<String> name;
Block* variable_statement =
- ParseVariableDeclarations(kForStatement, NULL, &name, CHECK_OK);
+ ParseVariableDeclarations(kForStatement, NULL, NULL, &name, CHECK_OK);
if (peek() == Token::IN && !name.is_null()) {
VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
@@ -2639,7 +2749,8 @@
Handle<String> name;
VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement =
- ParseVariableDeclarations(kForStatement, &decl_props, &name, CHECK_OK);
+ ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
+ CHECK_OK);
bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
if (peek() == Token::IN && accept_IN) {
// Rewrite a for-in statement of the form
@@ -3984,7 +4095,7 @@
Expression* value = ParseAssignmentExpression(true, CHECK_OK);
ObjectLiteral::Property* property =
- new(zone()) ObjectLiteral::Property(key, value);
+ new(zone()) ObjectLiteral::Property(key, value, isolate());
// Mark top-level object literals that contain function literals and
// pretenure the literal so it can be added as a constant function
@@ -4569,6 +4680,18 @@
}
+void Parser::ExpectContextualKeyword(const char* keyword, bool* ok) {
+ Expect(Token::IDENTIFIER, ok);
+ if (!*ok) return;
+ Handle<String> symbol = GetSymbol(ok);
+ if (!*ok) return;
+ if (!symbol->IsEqualTo(CStrVector(keyword))) {
+ *ok = false;
+ ReportUnexpectedToken(scanner().current_token());
+ }
+}
+
+
Literal* Parser::GetLiteralUndefined() {
return factory()->NewLiteral(isolate()->factory()->undefined_value());
}
diff --git a/src/parser.h b/src/parser.h
index 66c801d..dea73a1 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -566,6 +566,10 @@
ASSERT(top_scope_ != NULL);
return top_scope_->is_extended_mode();
}
+ Scope* DeclarationScope(VariableMode mode) {
+ return (mode == LET || mode == CONST_HARMONY)
+ ? top_scope_ : top_scope_->DeclarationScope();
+ }
// Check if the given string is 'eval' or 'arguments'.
bool IsEvalOrArguments(Handle<String> string);
@@ -577,23 +581,26 @@
void* ParseSourceElements(ZoneList<Statement*>* processor,
int end_token, bool* ok);
Statement* ParseModuleElement(ZoneStringList* labels, bool* ok);
- Block* ParseModuleDeclaration(bool* ok);
+ Block* ParseModuleDeclaration(ZoneStringList* names, bool* ok);
Module* ParseModule(bool* ok);
Module* ParseModuleLiteral(bool* ok);
Module* ParseModulePath(bool* ok);
Module* ParseModuleVariable(bool* ok);
Module* ParseModuleUrl(bool* ok);
+ Module* ParseModuleSpecifier(bool* ok);
Block* ParseImportDeclaration(bool* ok);
- Block* ParseExportDeclaration(bool* ok);
+ Statement* ParseExportDeclaration(bool* ok);
Statement* ParseBlockElement(ZoneStringList* labels, bool* ok);
Statement* ParseStatement(ZoneStringList* labels, bool* ok);
- Statement* ParseFunctionDeclaration(bool* ok);
+ Statement* ParseFunctionDeclaration(ZoneStringList* names, bool* ok);
Statement* ParseNativeDeclaration(bool* ok);
Block* ParseBlock(ZoneStringList* labels, bool* ok);
Block* ParseVariableStatement(VariableDeclarationContext var_context,
+ ZoneStringList* names,
bool* ok);
Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
VariableDeclarationProperties* decl_props,
+ ZoneStringList* names,
Handle<String>* out,
bool* ok);
Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
@@ -696,6 +703,7 @@
void Expect(Token::Value token, bool* ok);
bool Check(Token::Value token);
void ExpectSemicolon(bool* ok);
+ void ExpectContextualKeyword(const char* keyword, bool* ok);
Handle<String> LiteralString(PretenureFlag tenured) {
if (scanner().is_literal_ascii()) {
@@ -756,10 +764,8 @@
void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
// Parser support
- VariableProxy* Declare(Handle<String> name, VariableMode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok);
+ VariableProxy* NewUnresolved(Handle<String> name, VariableMode mode);
+ void Declare(Declaration* declaration, bool resolve, bool* ok);
bool TargetStackContainsLabel(Handle<String> label);
BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
index f3ec75a..0d8dadc 100644
--- a/src/prettyprinter.cc
+++ b/src/prettyprinter.cc
@@ -61,10 +61,15 @@
void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
Print("var ");
PrintLiteral(node->proxy()->name(), false);
- if (node->fun() != NULL) {
- Print(" = ");
- PrintFunctionLiteral(node->fun());
- }
+ Print(";");
+}
+
+
+void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
+ Print("function ");
+ PrintLiteral(node->proxy()->name(), false);
+ Print(" = ");
+ PrintFunctionLiteral(node->fun());
Print(";");
}
@@ -78,6 +83,22 @@
}
+void PrettyPrinter::VisitImportDeclaration(ImportDeclaration* node) {
+ Print("import ");
+ PrintLiteral(node->proxy()->name(), false);
+ Print(" from ");
+ Visit(node->module());
+ Print(";");
+}
+
+
+void PrettyPrinter::VisitExportDeclaration(ExportDeclaration* node) {
+ Print("export ");
+ PrintLiteral(node->proxy()->name(), false);
+ Print(";");
+}
+
+
void PrettyPrinter::VisitModuleLiteral(ModuleLiteral* node) {
VisitBlock(node->body());
}
@@ -744,19 +765,18 @@
void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
- if (node->fun() == NULL) {
- // var or const declarations
- PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
- node->proxy()->var(),
- node->proxy()->name());
- } else {
- // function declarations
- PrintIndented("FUNCTION ");
- PrintLiteral(node->proxy()->name(), true);
- Print(" = function ");
- PrintLiteral(node->fun()->name(), false);
- Print("\n");
- }
+ PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
+ node->proxy()->var(),
+ node->proxy()->name());
+}
+
+
+void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
+ PrintIndented("FUNCTION ");
+ PrintLiteral(node->proxy()->name(), true);
+ Print(" = function ");
+ PrintLiteral(node->fun()->name(), false);
+ Print("\n");
}
@@ -767,6 +787,19 @@
}
+void AstPrinter::VisitImportDeclaration(ImportDeclaration* node) {
+ IndentedScope indent(this, "IMPORT");
+ PrintLiteralIndented("NAME", node->proxy()->name(), true);
+ Visit(node->module());
+}
+
+
+void AstPrinter::VisitExportDeclaration(ExportDeclaration* node) {
+ IndentedScope indent(this, "EXPORT ");
+ PrintLiteral(node->proxy()->name(), true);
+}
+
+
void AstPrinter::VisitModuleLiteral(ModuleLiteral* node) {
VisitBlock(node->body());
}
diff --git a/src/property-details.h b/src/property-details.h
index c79aa96..81f521a 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -73,6 +73,26 @@
};
+inline bool IsRealProperty(PropertyType type) {
+ switch (type) {
+ case NORMAL:
+ case FIELD:
+ case CONSTANT_FUNCTION:
+ case CALLBACKS:
+ case HANDLER:
+ case INTERCEPTOR:
+ return true;
+ case MAP_TRANSITION:
+ case ELEMENTS_TRANSITION:
+ case CONSTANT_TRANSITION:
+ case NULL_DESCRIPTOR:
+ return false;
+ }
+ UNREACHABLE(); // keep the compiler happy
+ return false;
+}
+
+
// PropertyDetails captures type and attributes for a property.
// They are used both in property dictionaries and instance descriptors.
class PropertyDetails BASE_EMBEDDED {
diff --git a/src/property.h b/src/property.h
index 9235c32..d5efb7f 100644
--- a/src/property.h
+++ b/src/property.h
@@ -164,35 +164,6 @@
};
-template <class T>
-bool IsPropertyDescriptor(T* desc) {
- switch (desc->type()) {
- case NORMAL:
- case FIELD:
- case CONSTANT_FUNCTION:
- case HANDLER:
- case INTERCEPTOR:
- return true;
- case CALLBACKS: {
- Object* callback_object = desc->GetCallbackObject();
- // Non-JavaScript (i.e. native) accessors are always a property, otherwise
- // either the getter or the setter must be an accessor. Put another way:
- // If we only see map transitions and holes in a pair, this is not a
- // property.
- return (!callback_object->IsAccessorPair() ||
- AccessorPair::cast(callback_object)->ContainsAccessor());
- }
- case MAP_TRANSITION:
- case ELEMENTS_TRANSITION:
- case CONSTANT_TRANSITION:
- case NULL_DESCRIPTOR:
- return false;
- }
- UNREACHABLE(); // keep the compiler happy
- return false;
-}
-
-
class LookupResult BASE_EMBEDDED {
public:
explicit LookupResult(Isolate* isolate)
@@ -290,9 +261,10 @@
bool IsFound() { return lookup_type_ != NOT_FOUND; }
bool IsHandler() { return lookup_type_ == HANDLER_TYPE; }
- // Is the result is a property excluding transitions and the null descriptor?
+ // Is the result is a property excluding transitions and the null
+ // descriptor?
bool IsProperty() {
- return IsFound() && IsPropertyDescriptor(this);
+ return IsFound() && IsRealProperty(GetPropertyDetails().type());
}
bool IsCacheable() { return cacheable_; }
diff --git a/src/rewriter.cc b/src/rewriter.cc
index 8308792..55f93ee 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -210,7 +210,10 @@
// Do nothing:
void Processor::VisitVariableDeclaration(VariableDeclaration* node) {}
+void Processor::VisitFunctionDeclaration(FunctionDeclaration* node) {}
void Processor::VisitModuleDeclaration(ModuleDeclaration* node) {}
+void Processor::VisitImportDeclaration(ImportDeclaration* node) {}
+void Processor::VisitExportDeclaration(ExportDeclaration* node) {}
void Processor::VisitModuleLiteral(ModuleLiteral* node) {}
void Processor::VisitModuleVariable(ModuleVariable* node) {}
void Processor::VisitModulePath(ModulePath* node) {}
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index 8bd59d1..70586aa 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -257,7 +257,8 @@
}
}
- if (function->IsMarkedForLazyRecompilation()) {
+ if (function->IsMarkedForLazyRecompilation() &&
+ function->shared()->code()->kind() == Code::FUNCTION) {
Code* unoptimized = function->shared()->code();
int nesting = unoptimized->allow_osr_at_loop_nesting_level();
if (nesting == 0) AttemptOnStackReplacement(function);
diff --git a/src/runtime.cc b/src/runtime.cc
index fdbe1f5..d9c5bed 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -3763,7 +3763,7 @@
int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
- OffsetsVector registers(required_registers);
+ OffsetsVector registers(required_registers, isolate);
Vector<int32_t> register_vector(registers.vector(), registers.length());
int subject_length = subject->length();
bool first = true;
@@ -3836,7 +3836,7 @@
int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
- OffsetsVector registers(required_registers);
+ OffsetsVector registers(required_registers, isolate);
Vector<int32_t> register_vector(registers.vector(), registers.length());
RegExpImpl::IrregexpResult result =
@@ -3855,7 +3855,7 @@
if (result == RegExpImpl::RE_SUCCESS) {
// Need to keep a copy of the previous match for creating last_match_info
// at the end, so we have two vectors that we swap between.
- OffsetsVector registers2(required_registers);
+ OffsetsVector registers2(required_registers, isolate);
Vector<int> prev_register_vector(registers2.vector(), registers2.length());
bool first = true;
do {
@@ -9200,13 +9200,13 @@
return isolate->StackOverflow();
}
- return Execution::HandleStackGuardInterrupt();
+ return Execution::HandleStackGuardInterrupt(isolate);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
ASSERT(args.length() == 0);
- return Execution::HandleStackGuardInterrupt();
+ return Execution::HandleStackGuardInterrupt(isolate);
}
diff --git a/src/scopes.h b/src/scopes.h
index 30c95ee..9ce4cd7 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -372,6 +372,11 @@
// Determine if we can use lazy compilation for this scope.
bool AllowsLazyCompilation() const;
+ // True if we can lazily recompile functions with this scope.
+ bool allows_lazy_recompilation() const {
+ return !force_eager_compilation_;
+ }
+
// True if the outer context of this scope is always the global context.
bool HasTrivialOuterContext() const;
diff --git a/src/serialize.cc b/src/serialize.cc
index 81a94dd..8d8dbfd 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -273,14 +273,22 @@
STUB_CACHE_TABLE,
2,
"StubCache::primary_->value");
- Add(stub_cache->key_reference(StubCache::kSecondary).address(),
+ Add(stub_cache->map_reference(StubCache::kPrimary).address(),
STUB_CACHE_TABLE,
3,
+ "StubCache::primary_->map");
+ Add(stub_cache->key_reference(StubCache::kSecondary).address(),
+ STUB_CACHE_TABLE,
+ 4,
"StubCache::secondary_->key");
Add(stub_cache->value_reference(StubCache::kSecondary).address(),
STUB_CACHE_TABLE,
- 4,
+ 5,
"StubCache::secondary_->value");
+ Add(stub_cache->map_reference(StubCache::kSecondary).address(),
+ STUB_CACHE_TABLE,
+ 6,
+ "StubCache::secondary_->map");
// Runtime entries
Add(ExternalReference::perform_gc_function(isolate).address(),
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 4bbfe17..3371b1b 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -45,26 +45,13 @@
StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
ASSERT(isolate == Isolate::Current());
- memset(primary_, 0, sizeof(primary_[0]) * StubCache::kPrimaryTableSize);
- memset(secondary_, 0, sizeof(secondary_[0]) * StubCache::kSecondaryTableSize);
}
-void StubCache::Initialize(bool create_heap_objects) {
+void StubCache::Initialize() {
ASSERT(IsPowerOf2(kPrimaryTableSize));
ASSERT(IsPowerOf2(kSecondaryTableSize));
- if (create_heap_objects) {
- HandleScope scope;
- Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
- for (int i = 0; i < kPrimaryTableSize; i++) {
- primary_[i].key = heap()->empty_string();
- primary_[i].value = empty;
- }
- for (int j = 0; j < kSecondaryTableSize; j++) {
- secondary_[j].key = heap()->empty_string();
- secondary_[j].value = empty;
- }
- }
+ Clear();
}
@@ -90,14 +77,15 @@
// Compute the primary entry.
int primary_offset = PrimaryOffset(name, flags, map);
Entry* primary = entry(primary_, primary_offset);
- Code* hit = primary->value;
+ Code* old_code = primary->value;
// If the primary entry has useful data in it, we retire it to the
// secondary cache before overwriting it.
- if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
- Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
- int secondary_offset =
- SecondaryOffset(primary->key, primary_flags, primary_offset);
+ if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
+ Map* old_map = primary->map;
+ Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
+ int seed = PrimaryOffset(primary->key, old_flags, old_map);
+ int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
Entry* secondary = entry(secondary_, secondary_offset);
*secondary = *primary;
}
@@ -105,6 +93,8 @@
// Update primary cache.
primary->key = name;
primary->value = code;
+ primary->map = map;
+ isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
return code;
}
diff --git a/src/stub-cache.h b/src/stub-cache.h
index fdd8a12..29bdb61 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -69,9 +69,10 @@
struct Entry {
String* key;
Code* value;
+ Map* map;
};
- void Initialize(bool create_heap_objects);
+ void Initialize();
// Computes the right stub matching. Inserts the result in the
@@ -252,7 +253,7 @@
Handle<Context> global_context);
// Generate code for probing the stub cache table.
- // Arguments extra and extra2 may be used to pass additional scratch
+ // Arguments extra, extra2 and extra3 may be used to pass additional scratch
// registers. Set to no_reg if not needed.
void GenerateProbe(MacroAssembler* masm,
Code::Flags flags,
@@ -260,7 +261,8 @@
Register name,
Register scratch,
Register extra,
- Register extra2 = no_reg);
+ Register extra2 = no_reg,
+ Register extra3 = no_reg);
enum Table {
kPrimary,
@@ -274,6 +276,12 @@
}
+ SCTableReference map_reference(StubCache::Table table) {
+ return SCTableReference(
+ reinterpret_cast<Address>(&first_entry(table)->map));
+ }
+
+
SCTableReference value_reference(StubCache::Table table) {
return SCTableReference(
reinterpret_cast<Address>(&first_entry(table)->value));
@@ -300,7 +308,16 @@
RelocInfo::Mode mode,
Code::Kind kind);
- // Computes the hashed offsets for primary and secondary caches.
+ // The stub cache has a primary and secondary level. The two levels have
+ // different hashing algorithms in order to avoid simultaneous collisions
+ // in both caches. Unlike a probing strategy (quadratic or otherwise) the
+ // update strategy on updates is fairly clear and simple: Any existing entry
+ // in the primary cache is moved to the secondary cache, and secondary cache
+ // entries are overwritten.
+
+ // Hash algorithm for the primary table. This algorithm is replicated in
+ // assembler for every architecture. Returns an index into the table that
+ // is scaled by 1 << kHeapObjectTagSize.
static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
// This works well because the heap object tag size and the hash
// shift are equal. Shifting down the length field to get the
@@ -324,23 +341,30 @@
return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
}
+ // Hash algorithm for the secondary table. This algorithm is replicated in
+ // assembler for every architecture. Returns an index into the table that
+ // is scaled by 1 << kHeapObjectTagSize.
static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
// Use the seed from the primary cache in the secondary cache.
uint32_t string_low32bits =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
- uint32_t key = seed - string_low32bits + flags;
+ // We always set the in_loop bit to zero when generating the lookup code
+ // so do it here too so the hash codes match.
+ uint32_t iflags =
+ (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
+ uint32_t key = (seed - string_low32bits) + iflags;
return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
}
// Compute the entry for a given offset in exactly the same way as
// we do in generated code. We generate an hash code that already
- // ends in String::kHashShift 0s. Then we shift it so it is a multiple
+ // ends in String::kHashShift 0s. Then we multiply it so it is a multiple
// of sizeof(Entry). This makes it easier to avoid making mistakes
// in the hashed offset computations.
static Entry* entry(Entry* table, int offset) {
- const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
+ const int multiplier = sizeof(*table) >> String::kHashShift;
return reinterpret_cast<Entry*>(
- reinterpret_cast<Address>(table) + (offset << shift_amount));
+ reinterpret_cast<Address>(table) + offset * multiplier);
}
static const int kPrimaryTableBits = 11;
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 47341e7..6db9c77 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -198,6 +198,9 @@
SC(constructed_objects_stub, V8.ConstructedObjectsStub) \
SC(negative_lookups, V8.NegativeLookups) \
SC(negative_lookups_miss, V8.NegativeLookupsMiss) \
+ SC(megamorphic_stub_cache_probes, V8.MegamorphicStubCacheProbes) \
+ SC(megamorphic_stub_cache_misses, V8.MegamorphicStubCacheMisses) \
+ SC(megamorphic_stub_cache_updates, V8.MegamorphicStubCacheUpdates) \
SC(array_function_runtime, V8.ArrayFunctionRuntime) \
SC(array_function_native, V8.ArrayFunctionNative) \
SC(for_in, V8.ForIn) \
diff --git a/src/version.cc b/src/version.cc
index fbd6d93..0f0e01d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 9
-#define BUILD_NUMBER 12
+#define BUILD_NUMBER 13
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index abf9b56..4e037ff 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -330,10 +330,7 @@
}
// Store offset of return address for deoptimizer.
- // TODO(849): Once Generate_StringConstructCode doesn't reuse this
- // generator, we can drop the third condition below!
- if (!is_api_function && !count_constructions &&
- masm->isolate()->heap()->construct_stub_deopt_pc_offset() == 0) {
+ if (!is_api_function && !count_constructions) {
masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
}
@@ -1435,9 +1432,130 @@
void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
- // TODO(849): implement custom construct stub.
- // Generate a copy of the generic stub for now.
- Generate_JSConstructStubGeneric(masm);
+ // ----------- S t a t e -------------
+ // -- rax : number of arguments
+ // -- rdi : constructor function
+ // -- rsp[0] : return address
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
+ // -- rsp[(argc + 1) * 8] : receiver
+ // -----------------------------------
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->string_ctor_calls(), 1);
+
+ if (FLAG_debug_code) {
+ __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx);
+ __ cmpq(rdi, rcx);
+ __ Assert(equal, "Unexpected String function");
+ }
+
+ // Load the first argument into rax and get rid of the rest
+ // (including the receiver).
+ Label no_arguments;
+ __ testq(rax, rax);
+ __ j(zero, &no_arguments);
+ __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
+ __ pop(rcx);
+ __ lea(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
+ __ push(rcx);
+ __ movq(rax, rbx);
+
+ // Lookup the argument in the number to string cache.
+ Label not_cached, argument_is_string;
+ NumberToStringStub::GenerateLookupNumberStringCache(
+ masm,
+ rax, // Input.
+ rbx, // Result.
+ rcx, // Scratch 1.
+ rdx, // Scratch 2.
+ false, // Input is known to be smi?
+ ¬_cached);
+ __ IncrementCounter(counters->string_ctor_cached_number(), 1);
+ __ bind(&argument_is_string);
+
+ // ----------- S t a t e -------------
+ // -- rbx : argument converted to string
+ // -- rdi : constructor function
+ // -- rsp[0] : return address
+ // -----------------------------------
+
+ // Allocate a JSValue and put the tagged pointer into rax.
+ Label gc_required;
+ __ AllocateInNewSpace(JSValue::kSize,
+ rax, // Result.
+ rcx, // New allocation top (we ignore it).
+ no_reg,
+ &gc_required,
+ TAG_OBJECT);
+
+ // Set the map.
+ __ LoadGlobalFunctionInitialMap(rdi, rcx);
+ if (FLAG_debug_code) {
+ __ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset),
+ Immediate(JSValue::kSize >> kPointerSizeLog2));
+ __ Assert(equal, "Unexpected string wrapper instance size");
+ __ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0));
+ __ Assert(equal, "Unexpected unused properties of string wrapper");
+ }
+ __ movq(FieldOperand(rax, HeapObject::kMapOffset), rcx);
+
+ // Set properties and elements.
+ __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
+ __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rcx);
+ __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx);
+
+ // Set the value.
+ __ movq(FieldOperand(rax, JSValue::kValueOffset), rbx);
+
+ // Ensure the object is fully initialized.
+ STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
+
+ // We're done. Return.
+ __ ret(0);
+
+ // The argument was not found in the number to string cache. Check
+ // if it's a string already before calling the conversion builtin.
+ Label convert_argument;
+ __ bind(¬_cached);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ JumpIfSmi(rax, &convert_argument);
+ Condition is_string = masm->IsObjectStringType(rax, rbx, rcx);
+ __ j(NegateCondition(is_string), &convert_argument);
+ __ movq(rbx, rax);
+ __ IncrementCounter(counters->string_ctor_string_value(), 1);
+ __ jmp(&argument_is_string);
+
+ // Invoke the conversion builtin and put the result into rbx.
+ __ bind(&convert_argument);
+ __ IncrementCounter(counters->string_ctor_conversions(), 1);
+ {
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ push(rdi); // Preserve the function.
+ __ push(rax);
+ __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
+ __ pop(rdi);
+ }
+ __ movq(rbx, rax);
+ __ jmp(&argument_is_string);
+
+ // Load the empty string into rbx, remove the receiver from the
+ // stack, and jump back to the case where the argument is a string.
+ __ bind(&no_arguments);
+ __ LoadRoot(rbx, Heap::kEmptyStringRootIndex);
+ __ pop(rcx);
+ __ lea(rsp, Operand(rsp, kPointerSize));
+ __ push(rcx);
+ __ jmp(&argument_is_string);
+
+ // At this point the argument is already a string. Call runtime to
+ // create a string wrapper.
+ __ bind(&gc_required);
+ __ IncrementCounter(counters->string_ctor_gc_required(), 1);
+ {
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ push(rbx);
+ __ CallRuntime(Runtime::kNewStringWrapper, 1);
+ }
+ __ ret(0);
}
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 65d57e0..45a0508 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -469,7 +469,7 @@
void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
- LInstructionGap* gap = new LInstructionGap(block);
+ LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
int index = -1;
if (instr->IsControl()) {
instructions_.Add(gap);
@@ -544,7 +544,7 @@
LChunk* LChunkBuilder::Build() {
ASSERT(is_unused());
- chunk_ = new LChunk(info(), graph());
+ chunk_ = new(zone()) LChunk(info(), graph());
HPhase phase("Building chunk", chunk_);
status_ = BUILDING;
const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
@@ -575,14 +575,14 @@
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new LUnallocated(LUnallocated::FIXED_REGISTER,
- Register::ToAllocationIndex(reg));
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
- return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
- XMMRegister::ToAllocationIndex(reg));
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ XMMRegister::ToAllocationIndex(reg));
}
@@ -597,29 +597,29 @@
LOperand* LChunkBuilder::UseRegister(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
}
LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
return Use(value,
- new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
LUnallocated::USED_AT_START));
}
LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
}
LOperand* LChunkBuilder::Use(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::NONE));
+ return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
}
LOperand* LChunkBuilder::UseAtStart(HValue* value) {
- return Use(value, new LUnallocated(LUnallocated::NONE,
+ return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
LUnallocated::USED_AT_START));
}
@@ -655,7 +655,7 @@
LOperand* LChunkBuilder::UseAny(HValue* value) {
return value->IsConstant()
? chunk_->DefineConstantOperand(HConstant::cast(value))
- : Use(value, new LUnallocated(LUnallocated::ANY));
+ : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
}
@@ -681,7 +681,8 @@
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsRegister(
LTemplateInstruction<1, I, T>* instr) {
- return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
}
@@ -689,14 +690,16 @@
LInstruction* LChunkBuilder::DefineAsSpilled(
LTemplateInstruction<1, I, T>* instr,
int index) {
- return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
}
template<int I, int T>
LInstruction* LChunkBuilder::DefineSameAsFirst(
LTemplateInstruction<1, I, T>* instr) {
- return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
+ return Define(instr,
+ new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
}
@@ -779,13 +782,14 @@
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
ASSERT(!instr->HasPointerMap());
- instr->set_pointer_map(new LPointerMap(position_));
+ instr->set_pointer_map(new(zone()) LPointerMap(position_));
return instr;
}
LUnallocated* LChunkBuilder::TempRegister() {
- LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
+ LUnallocated* operand =
+ new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
operand->set_virtual_register(allocator_->GetVirtualRegister());
if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
return operand;
@@ -807,17 +811,17 @@
LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
- return new LLabel(instr->block());
+ return new(zone()) LLabel(instr->block());
}
LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
- return AssignEnvironment(new LDeoptimize);
+ return AssignEnvironment(new(zone()) LDeoptimize);
}
LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
- return AssignEnvironment(new LDeoptimize);
+ return AssignEnvironment(new(zone()) LDeoptimize);
}
@@ -829,7 +833,7 @@
LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
- LArithmeticT* result = new LArithmeticT(op, left, right);
+ LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -863,7 +867,7 @@
}
LInstruction* result =
- DefineSameAsFirst(new LShiftI(op, left, right, does_deopt));
+ DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
return does_deopt ? AssignEnvironment(result) : result;
}
@@ -876,7 +880,7 @@
ASSERT(op != Token::MOD);
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- LArithmeticD* result = new LArithmeticD(op, left, right);
+ LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
return DefineSameAsFirst(result);
}
@@ -894,7 +898,8 @@
ASSERT(right->representation().IsTagged());
LOperand* left_operand = UseFixed(left, rdx);
LOperand* right_operand = UseFixed(right, rax);
- LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
+ LArithmeticT* result =
+ new(zone()) LArithmeticT(op, left_operand, right_operand);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -993,13 +998,14 @@
ASSERT(ast_id != AstNode::kNoNumber ||
hydrogen_env->frame_type() != JS_FUNCTION);
int value_count = hydrogen_env->length();
- LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
- hydrogen_env->frame_type(),
- ast_id,
- hydrogen_env->parameter_count(),
- argument_count_,
- value_count,
- outer);
+ LEnvironment* result = new(zone()) LEnvironment(
+ hydrogen_env->closure(),
+ hydrogen_env->frame_type(),
+ ast_id,
+ hydrogen_env->parameter_count(),
+ argument_count_,
+ value_count,
+ outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue;
@@ -1009,7 +1015,7 @@
if (value->IsArgumentsObject()) {
op = NULL;
} else if (value->IsPushArgument()) {
- op = new LArgument(argument_index++);
+ op = new(zone()) LArgument(argument_index++);
} else {
op = UseAny(value);
}
@@ -1025,7 +1031,7 @@
LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
- return new LGoto(instr->FirstSuccessor()->block_id());
+ return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
}
@@ -1037,10 +1043,10 @@
HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
- return new LGoto(successor->block_id());
+ return new(zone()) LGoto(successor->block_id());
}
- LBranch* result = new LBranch(UseRegister(value));
+ LBranch* result = new(zone()) LBranch(UseRegister(value));
// Tagged values that are not known smis or booleans require a
// deoptimization environment.
Representation rep = value->representation();
@@ -1055,24 +1061,24 @@
LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
- return new LCmpMapAndBranch(value);
+ return new(zone()) LCmpMapAndBranch(value);
}
LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
- return DefineAsRegister(new LArgumentsLength(Use(length->value())));
+ return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
}
LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
- return DefineAsRegister(new LArgumentsElements);
+ return DefineAsRegister(new(zone()) LArgumentsElements);
}
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LOperand* left = UseFixed(instr->left(), rax);
LOperand* right = UseFixed(instr->right(), rdx);
- LInstanceOf* result = new LInstanceOf(left, right);
+ LInstanceOf* result = new(zone()) LInstanceOf(left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1080,8 +1086,8 @@
LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
HInstanceOfKnownGlobal* instr) {
LInstanceOfKnownGlobal* result =
- new LInstanceOfKnownGlobal(UseFixed(instr->left(), rax),
- FixedTemp(rdi));
+ new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), rax),
+ FixedTemp(rdi));
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1091,7 +1097,7 @@
LOperand* receiver = UseFixed(instr->receiver(), rax);
LOperand* length = UseFixed(instr->length(), rbx);
LOperand* elements = UseFixed(instr->elements(), rcx);
- LApplyArguments* result = new LApplyArguments(function,
+ LApplyArguments* result = new(zone()) LApplyArguments(function,
receiver,
length,
elements);
@@ -1102,53 +1108,55 @@
LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
++argument_count_;
LOperand* argument = UseOrConstant(instr->argument());
- return new LPushArgument(argument);
+ return new(zone()) LPushArgument(argument);
}
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
+ return instr->HasNoUses()
+ ? NULL
+ : DefineAsRegister(new(zone()) LThisFunction);
}
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
+ return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
}
LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LOuterContext(context));
+ return DefineAsRegister(new(zone()) LOuterContext(context));
}
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
- return MarkAsCall(new LDeclareGlobals, instr);
+ return MarkAsCall(new(zone()) LDeclareGlobals, instr);
}
LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
- return DefineAsRegister(new LGlobalObject);
+ return DefineAsRegister(new(zone()) LGlobalObject);
}
LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
LOperand* global_object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGlobalReceiver(global_object));
+ return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
}
LInstruction* LChunkBuilder::DoCallConstantFunction(
HCallConstantFunction* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallConstantFunction, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr);
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* function = UseFixed(instr->function(), rdi);
argument_count_ -= instr->argument_count();
- LInvokeFunction* result = new LInvokeFunction(function);
+ LInvokeFunction* result = new(zone()) LInvokeFunction(function);
return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
}
@@ -1157,11 +1165,11 @@
BuiltinFunctionId op = instr->op();
if (op == kMathLog || op == kMathSin || op == kMathCos) {
LOperand* input = UseFixedDouble(instr->value(), xmm1);
- LUnaryMathOperation* result = new LUnaryMathOperation(input);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
} else {
LOperand* input = UseRegisterAtStart(instr->value());
- LUnaryMathOperation* result = new LUnaryMathOperation(input);
+ LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input);
switch (op) {
case kMathAbs:
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
@@ -1185,33 +1193,33 @@
ASSERT(instr->key()->representation().IsTagged());
LOperand* key = UseFixed(instr->key(), rcx);
argument_count_ -= instr->argument_count();
- LCallKeyed* result = new LCallKeyed(key);
+ LCallKeyed* result = new(zone()) LCallKeyed(key);
return MarkAsCall(DefineFixed(result, rax), instr);
}
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallNamed, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallNamed, rax), instr);
}
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallGlobal, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr);
}
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallKnownGlobal, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr);
}
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
LOperand* constructor = UseFixed(instr->constructor(), rdi);
argument_count_ -= instr->argument_count();
- LCallNew* result = new LCallNew(constructor);
+ LCallNew* result = new(zone()) LCallNew(constructor);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1219,14 +1227,14 @@
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
LOperand* function = UseFixed(instr->function(), rdi);
argument_count_ -= instr->argument_count();
- LCallFunction* result = new LCallFunction(function);
+ LCallFunction* result = new(zone()) LCallFunction(function);
return MarkAsCall(DefineFixed(result, rax), instr);
}
LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallRuntime, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, rax), instr);
}
@@ -1252,7 +1260,7 @@
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- return DefineSameAsFirst(new LBitI(left, right));
+ return DefineSameAsFirst(new(zone()) LBitI(left, right));
} else {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged());
@@ -1260,7 +1268,7 @@
LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
- LArithmeticT* result = new LArithmeticT(instr->op(), left, right);
+ LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}
}
@@ -1270,7 +1278,7 @@
ASSERT(instr->value()->representation().IsInteger32());
ASSERT(instr->representation().IsInteger32());
LOperand* input = UseRegisterAtStart(instr->value());
- LBitNotI* result = new LBitNotI(input);
+ LBitNotI* result = new(zone()) LBitNotI(input);
return DefineSameAsFirst(result);
}
@@ -1284,7 +1292,7 @@
LOperand* temp = FixedTemp(rdx);
LOperand* dividend = UseFixed(instr->left(), rax);
LOperand* divisor = UseRegister(instr->right());
- LDivI* result = new LDivI(dividend, divisor, temp);
+ LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
return AssignEnvironment(DefineFixed(result, rax));
} else {
ASSERT(instr->representation().IsTagged());
@@ -1302,7 +1310,8 @@
if (instr->HasPowerOf2Divisor()) {
ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
LOperand* value = UseRegisterAtStart(instr->left());
- LModI* mod = new LModI(value, UseOrConstant(instr->right()), NULL);
+ LModI* mod =
+ new(zone()) LModI(value, UseOrConstant(instr->right()), NULL);
result = DefineSameAsFirst(mod);
} else {
// The temporary operand is necessary to ensure that right is not
@@ -1310,7 +1319,7 @@
LOperand* temp = FixedTemp(rdx);
LOperand* value = UseFixed(instr->left(), rax);
LOperand* divisor = UseRegister(instr->right());
- LModI* mod = new LModI(value, divisor, temp);
+ LModI* mod = new(zone()) LModI(value, divisor, temp);
result = DefineFixed(mod, rdx);
}
@@ -1327,7 +1336,7 @@
// TODO(fschneider): Allow any register as input registers.
LOperand* left = UseFixedDouble(instr->left(), xmm2);
LOperand* right = UseFixedDouble(instr->right(), xmm1);
- LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
+ LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
}
}
@@ -1339,7 +1348,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstant(instr->MostConstantOperand());
- LMulI* mul = new LMulI(left, right);
+ LMulI* mul = new(zone()) LMulI(left, right);
if (instr->CheckFlag(HValue::kCanOverflow) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
AssignEnvironment(mul);
@@ -1360,7 +1369,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
- LSubI* sub = new LSubI(left, right);
+ LSubI* sub = new(zone()) LSubI(left, right);
LInstruction* result = DefineSameAsFirst(sub);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
@@ -1381,7 +1390,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
- LAddI* add = new LAddI(left, right);
+ LAddI* add = new(zone()) LAddI(left, right);
LInstruction* result = DefineSameAsFirst(add);
if (instr->CheckFlag(HValue::kCanOverflow)) {
result = AssignEnvironment(result);
@@ -1411,7 +1420,7 @@
#else
UseFixed(instr->right(), rdi);
#endif
- LPower* result = new LPower(left, right);
+ LPower* result = new(zone()) LPower(left, right);
return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
CAN_DEOPTIMIZE_EAGERLY);
}
@@ -1425,7 +1434,7 @@
#else
LOperand* global_object = UseFixed(instr->global_object(), rdi);
#endif
- LRandom* result = new LRandom(global_object);
+ LRandom* result = new(zone()) LRandom(global_object);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
}
@@ -1435,7 +1444,7 @@
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
- LCmpT* result = new LCmpT(left, right);
+ LCmpT* result = new(zone()) LCmpT(left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1448,7 +1457,7 @@
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
- return new LCmpIDAndBranch(left, right);
+ return new(zone()) LCmpIDAndBranch(left, right);
} else {
ASSERT(r.IsDouble());
ASSERT(instr->left()->representation().IsDouble());
@@ -1462,7 +1471,7 @@
left = UseRegisterAtStart(instr->left());
right = UseRegisterAtStart(instr->right());
}
- return new LCmpIDAndBranch(left, right);
+ return new(zone()) LCmpIDAndBranch(left, right);
}
}
@@ -1471,47 +1480,50 @@
HCompareObjectEqAndBranch* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
- return new LCmpObjectEqAndBranch(left, right);
+ return new(zone()) LCmpObjectEqAndBranch(left, right);
}
LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
HCompareConstantEqAndBranch* instr) {
- return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value()));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LCmpConstantEqAndBranch(value);
}
LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* temp = instr->kind() == kStrictEquality ? NULL : TempRegister();
- return new LIsNilAndBranch(UseRegisterAtStart(instr->value()), temp);
+ return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()), temp);
}
LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
+ return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
}
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
+ LOperand* value = UseRegisterAtStart(instr->value());
LOperand* temp = TempRegister();
- return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp);
+ return new(zone()) LIsStringAndBranch(value, temp);
}
LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsSmiAndBranch(Use(instr->value()));
+ return new(zone()) LIsSmiAndBranch(Use(instr->value()));
}
LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
HIsUndetectableAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()),
- TempRegister());
+ LOperand* value = UseRegisterAtStart(instr->value());
+ LOperand* temp = TempRegister();
+ return new(zone()) LIsUndetectableAndBranch(value, temp);
}
@@ -1522,7 +1534,8 @@
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
- LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right);
+ LStringCompareAndBranch* result =
+ new(zone()) LStringCompareAndBranch(left, right);
return MarkAsCall(result, instr);
}
@@ -1531,7 +1544,8 @@
LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
HHasInstanceTypeAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value()));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LHasInstanceTypeAndBranch(value);
}
@@ -1540,55 +1554,57 @@
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LGetCachedArrayIndex(value));
+ return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
}
LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
HHasCachedArrayIndexAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
- return new LHasCachedArrayIndexAndBranch(UseRegisterAtStart(instr->value()));
+ LOperand* value = UseRegisterAtStart(instr->value());
+ return new(zone()) LHasCachedArrayIndexAndBranch(value);
}
LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
HClassOfTestAndBranch* instr) {
- return new LClassOfTestAndBranch(UseRegister(instr->value()),
- TempRegister(),
- TempRegister());
+ LOperand* value = UseRegister(instr->value());
+ return new(zone()) LClassOfTestAndBranch(value,
+ TempRegister(),
+ TempRegister());
}
LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LJSArrayLength(array));
+ return DefineAsRegister(new(zone()) LJSArrayLength(array));
}
LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
HFixedArrayBaseLength* instr) {
LOperand* array = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LFixedArrayBaseLength(array));
+ return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
}
LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
LOperand* object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LElementsKind(object));
+ return DefineAsRegister(new(zone()) LElementsKind(object));
}
LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
LOperand* object = UseRegister(instr->value());
- LValueOf* result = new LValueOf(object);
+ LValueOf* result = new(zone()) LValueOf(object);
return DefineSameAsFirst(result);
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
- return AssignEnvironment(new LBoundsCheck(
- UseRegisterOrConstantAtStart(instr->index()),
- Use(instr->length())));
+ LOperand* value = UseRegisterOrConstantAtStart(instr->index());
+ LOperand* length = Use(instr->length());
+ return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
}
@@ -1601,7 +1617,7 @@
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
LOperand* value = UseFixed(instr->value(), rax);
- return MarkAsCall(new LThrow(value), instr);
+ return MarkAsCall(new(zone()) LThrow(value), instr);
}
@@ -1624,7 +1640,7 @@
if (from.IsTagged()) {
if (to.IsDouble()) {
LOperand* value = UseRegister(instr->value());
- LNumberUntagD* res = new LNumberUntagD(value);
+ LNumberUntagD* res = new(zone()) LNumberUntagD(value);
return AssignEnvironment(DefineAsRegister(res));
} else {
ASSERT(to.IsInteger32());
@@ -1633,10 +1649,10 @@
if (needs_check) {
bool truncating = instr->CanTruncateToInt32();
LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
- LTaggedToI* res = new LTaggedToI(value, xmm_temp);
+ LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp);
return AssignEnvironment(DefineSameAsFirst(res));
} else {
- return DefineSameAsFirst(new LSmiUntag(value, needs_check));
+ return DefineSameAsFirst(new(zone()) LSmiUntag(value, needs_check));
}
}
} else if (from.IsDouble()) {
@@ -1646,26 +1662,27 @@
// Make sure that temp and result_temp are different registers.
LUnallocated* result_temp = TempRegister();
- LNumberTagD* result = new LNumberTagD(value, temp);
+ LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
return AssignPointerMap(Define(result, result_temp));
} else {
ASSERT(to.IsInteger32());
LOperand* value = UseRegister(instr->value());
- return AssignEnvironment(DefineAsRegister(new LDoubleToI(value)));
+ return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToI(value)));
}
} else if (from.IsInteger32()) {
if (to.IsTagged()) {
HValue* val = instr->value();
LOperand* value = UseRegister(val);
if (val->HasRange() && val->range()->IsInSmiRange()) {
- return DefineSameAsFirst(new LSmiTag(value));
+ return DefineSameAsFirst(new(zone()) LSmiTag(value));
} else {
- LNumberTagI* result = new LNumberTagI(value);
+ LNumberTagI* result = new(zone()) LNumberTagI(value);
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
}
} else {
ASSERT(to.IsDouble());
- return DefineAsRegister(new LInteger32ToDouble(Use(instr->value())));
+ LOperand* value = Use(instr->value());
+ return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
}
}
UNREACHABLE();
@@ -1675,39 +1692,39 @@
LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckNonSmi(value));
+ return AssignEnvironment(new(zone()) LCheckNonSmi(value));
}
LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- LCheckInstanceType* result = new LCheckInstanceType(value);
+ LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
return AssignEnvironment(result);
}
LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
LOperand* temp = TempRegister();
- LCheckPrototypeMaps* result = new LCheckPrototypeMaps(temp);
+ LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp);
return AssignEnvironment(result);
}
LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckSmi(value));
+ return AssignEnvironment(new(zone()) LCheckSmi(value));
}
LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- return AssignEnvironment(new LCheckFunction(value));
+ return AssignEnvironment(new(zone()) LCheckFunction(value));
}
LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
- LCheckMap* result = new LCheckMap(value);
+ LCheckMap* result = new(zone()) LCheckMap(value);
return AssignEnvironment(result);
}
@@ -1717,17 +1734,17 @@
Representation input_rep = value->representation();
LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) {
- return DefineAsRegister(new LClampDToUint8(reg,
+ return DefineAsRegister(new(zone()) LClampDToUint8(reg,
TempRegister()));
} else if (input_rep.IsInteger32()) {
- return DefineSameAsFirst(new LClampIToUint8(reg));
+ return DefineSameAsFirst(new(zone()) LClampIToUint8(reg));
} else {
ASSERT(input_rep.IsTagged());
// Register allocator doesn't (yet) support allocation of double
// temps. Reserve xmm1 explicitly.
- LClampTToUint8* result = new LClampTToUint8(reg,
- TempRegister(),
- FixedTemp(xmm1));
+ LClampTToUint8* result = new(zone()) LClampTToUint8(reg,
+ TempRegister(),
+ FixedTemp(xmm1));
return AssignEnvironment(DefineSameAsFirst(result));
}
}
@@ -1738,7 +1755,7 @@
Representation input_rep = value->representation();
LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) {
- return AssignEnvironment(DefineAsRegister(new LDoubleToI(reg)));
+ return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToI(reg)));
} else if (input_rep.IsInteger32()) {
// Canonicalization should already have removed the hydrogen instruction in
// this case, since it is a noop.
@@ -1754,25 +1771,25 @@
? NULL
: FixedTemp(xmm1);
return AssignEnvironment(
- DefineSameAsFirst(new LTaggedToI(reg, xmm_temp)));
+ DefineSameAsFirst(new(zone()) LTaggedToI(reg, xmm_temp)));
}
}
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
- return new LReturn(UseFixed(instr->value(), rax));
+ return new(zone()) LReturn(UseFixed(instr->value(), rax));
}
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
Representation r = instr->representation();
if (r.IsInteger32()) {
- return DefineAsRegister(new LConstantI);
+ return DefineAsRegister(new(zone()) LConstantI);
} else if (r.IsDouble()) {
LOperand* temp = TempRegister();
- return DefineAsRegister(new LConstantD(temp));
+ return DefineAsRegister(new(zone()) LConstantD(temp));
} else if (r.IsTagged()) {
- return DefineAsRegister(new LConstantT);
+ return DefineAsRegister(new(zone()) LConstantT);
} else {
UNREACHABLE();
return NULL;
@@ -1781,7 +1798,7 @@
LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
- LLoadGlobalCell* result = new LLoadGlobalCell;
+ LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
return instr->RequiresHoleCheck()
? AssignEnvironment(DefineAsRegister(result))
: DefineAsRegister(result);
@@ -1790,7 +1807,7 @@
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* global_object = UseFixed(instr->global_object(), rax);
- LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
+ LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1800,22 +1817,24 @@
// Use a temp to avoid reloading the cell value address in the case where
// we perform a hole check.
return instr->RequiresHoleCheck()
- ? AssignEnvironment(new LStoreGlobalCell(value, TempRegister()))
- : new LStoreGlobalCell(value, NULL);
+ ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
+ : new(zone()) LStoreGlobalCell(value, NULL);
}
LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
LOperand* global_object = UseFixed(instr->global_object(), rdx);
LOperand* value = UseFixed(instr->value(), rax);
- LStoreGlobalGeneric* result = new LStoreGlobalGeneric(global_object, value);
+ LStoreGlobalGeneric* result = new(zone()) LStoreGlobalGeneric(global_object,
+ value);
return MarkAsCall(result, instr);
}
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
- LInstruction* result = DefineAsRegister(new LLoadContextSlot(context));
+ LInstruction* result =
+ DefineAsRegister(new(zone()) LLoadContextSlot(context));
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
}
@@ -1833,7 +1852,7 @@
value = UseRegister(instr->value());
temp = NULL;
}
- LInstruction* result = new LStoreContextSlot(context, value, temp);
+ LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
}
@@ -1841,7 +1860,7 @@
LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
ASSERT(instr->representation().IsTagged());
LOperand* obj = UseRegisterAtStart(instr->object());
- return DefineAsRegister(new LLoadNamedField(obj));
+ return DefineAsRegister(new(zone()) LLoadNamedField(obj));
}
@@ -1850,11 +1869,13 @@
ASSERT(instr->representation().IsTagged());
if (instr->need_generic()) {
LOperand* obj = UseFixed(instr->object(), rax);
- LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
return MarkAsCall(DefineFixed(result, rax), instr);
} else {
LOperand* obj = UseRegisterAtStart(instr->object());
- LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
+ LLoadNamedFieldPolymorphic* result =
+ new(zone()) LLoadNamedFieldPolymorphic(obj);
return AssignEnvironment(DefineAsRegister(result));
}
}
@@ -1862,7 +1883,7 @@
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object = UseFixed(instr->object(), rax);
- LLoadNamedGeneric* result = new LLoadNamedGeneric(object);
+ LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(object);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1870,20 +1891,20 @@
LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
HLoadFunctionPrototype* instr) {
return AssignEnvironment(DefineAsRegister(
- new LLoadFunctionPrototype(UseRegister(instr->function()))));
+ new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
}
LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadElements(input));
+ return DefineAsRegister(new(zone()) LLoadElements(input));
}
LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
HLoadExternalArrayPointer* instr) {
LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LLoadExternalArrayPointer(input));
+ return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
}
@@ -1893,7 +1914,7 @@
ASSERT(instr->key()->representation().IsInteger32());
LOperand* obj = UseRegisterAtStart(instr->object());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
+ LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
if (instr->RequiresHoleCheck()) AssignEnvironment(result);
return DefineAsRegister(result);
}
@@ -1906,7 +1927,7 @@
LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
- new LLoadKeyedFastDoubleElement(elements, key);
+ new(zone()) LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
@@ -1925,7 +1946,7 @@
LOperand* external_pointer = UseRegister(instr->external_pointer());
LOperand* key = UseRegisterOrConstant(instr->key());
LLoadKeyedSpecializedArrayElement* result =
- new LLoadKeyedSpecializedArrayElement(external_pointer, key);
+ new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
LInstruction* load_instr = DefineAsRegister(result);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
@@ -1938,7 +1959,7 @@
LOperand* object = UseFixed(instr->object(), rdx);
LOperand* key = UseFixed(instr->key(), rax);
- LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key);
+ LLoadKeyedGeneric* result = new(zone()) LLoadKeyedGeneric(object, key);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1957,7 +1978,7 @@
LOperand* key = needs_write_barrier
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
- return new LStoreKeyedFastElement(obj, key, val);
+ return new(zone()) LStoreKeyedFastElement(obj, key, val);
}
@@ -1971,7 +1992,7 @@
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- return new LStoreKeyedFastDoubleElement(elements, key, val);
+ return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
}
@@ -1997,9 +2018,9 @@
: UseRegister(instr->value());
LOperand* key = UseRegisterOrConstant(instr->key());
- return new LStoreKeyedSpecializedArrayElement(external_pointer,
- key,
- val);
+ return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
+ key,
+ val);
}
@@ -2012,7 +2033,8 @@
ASSERT(instr->key()->representation().IsTagged());
ASSERT(instr->value()->representation().IsTagged());
- LStoreKeyedGeneric* result = new LStoreKeyedGeneric(object, key, value);
+ LStoreKeyedGeneric* result =
+ new(zone()) LStoreKeyedGeneric(object, key, value);
return MarkAsCall(result, instr);
}
@@ -2025,14 +2047,16 @@
LOperand* new_map_reg = TempRegister();
LOperand* temp_reg = TempRegister();
LTransitionElementsKind* result =
- new LTransitionElementsKind(object, new_map_reg, temp_reg);
+ new(zone()) LTransitionElementsKind(object, new_map_reg, temp_reg);
return DefineSameAsFirst(result);
} else {
LOperand* object = UseFixed(instr->object(), rax);
LOperand* fixed_object_reg = FixedTemp(rdx);
LOperand* new_map_reg = FixedTemp(rbx);
LTransitionElementsKind* result =
- new LTransitionElementsKind(object, new_map_reg, fixed_object_reg);
+ new(zone()) LTransitionElementsKind(object,
+ new_map_reg,
+ fixed_object_reg);
return MarkAsCall(DefineFixed(result, rax), instr);
}
}
@@ -2054,7 +2078,7 @@
LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
? TempRegister() : NULL;
- return new LStoreNamedField(obj, val, temp);
+ return new(zone()) LStoreNamedField(obj, val, temp);
}
@@ -2062,7 +2086,7 @@
LOperand* object = UseFixed(instr->object(), rdx);
LOperand* value = UseFixed(instr->value(), rax);
- LStoreNamedGeneric* result = new LStoreNamedGeneric(object, value);
+ LStoreNamedGeneric* result = new(zone()) LStoreNamedGeneric(object, value);
return MarkAsCall(result, instr);
}
@@ -2070,28 +2094,29 @@
LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
LOperand* left = UseOrConstantAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
- return MarkAsCall(DefineFixed(new LStringAdd(left, right), rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), rax),
+ instr);
}
LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
LOperand* string = UseTempRegister(instr->string());
LOperand* index = UseTempRegister(instr->index());
- LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
+ LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
}
LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
LOperand* char_code = UseRegister(instr->value());
- LStringCharFromCode* result = new LStringCharFromCode(char_code);
+ LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
return AssignPointerMap(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
LOperand* string = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new LStringLength(string));
+ return DefineAsRegister(new(zone()) LStringLength(string));
}
@@ -2102,34 +2127,34 @@
LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
- return MarkAsCall(DefineFixed(new LFastLiteral, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, rax), instr);
}
LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
- return MarkAsCall(DefineFixed(new LArrayLiteral, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, rax), instr);
}
LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
- return MarkAsCall(DefineFixed(new LObjectLiteral, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, rax), instr);
}
LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
- return MarkAsCall(DefineFixed(new LRegExpLiteral, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, rax), instr);
}
LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
- return MarkAsCall(DefineFixed(new LFunctionLiteral, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, rax), instr);
}
LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
- LDeleteProperty* result =
- new LDeleteProperty(UseAtStart(instr->object()),
- UseOrConstantAtStart(instr->key()));
+ LOperand* object = UseAtStart(instr->object());
+ LOperand* key = UseOrConstantAtStart(instr->key());
+ LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -2137,13 +2162,13 @@
LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
allocator_->MarkAsOsrEntry();
current_block_->last_environment()->set_ast_id(instr->ast_id());
- return AssignEnvironment(new LOsrEntry);
+ return AssignEnvironment(new(zone()) LOsrEntry);
}
LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
int spill_index = chunk()->GetParameterStackSlot(instr->index());
- return DefineAsSpilled(new LParameter, spill_index);
+ return DefineAsSpilled(new(zone()) LParameter, spill_index);
}
@@ -2153,13 +2178,13 @@
Abort("Too many spill slots needed for OSR");
spill_index = 0;
}
- return DefineAsSpilled(new LUnknownOSRValue, spill_index);
+ return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
}
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
argument_count_ -= instr->argument_count();
- return MarkAsCall(DefineFixed(new LCallStub, rax), instr);
+ return MarkAsCall(DefineFixed(new(zone()) LCallStub, rax), instr);
}
@@ -2176,32 +2201,33 @@
LOperand* arguments = UseRegister(instr->arguments());
LOperand* length = UseTempRegister(instr->length());
LOperand* index = Use(instr->index());
- LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
+ LAccessArgumentsAt* result =
+ new(zone()) LAccessArgumentsAt(arguments, length, index);
return AssignEnvironment(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
LOperand* object = UseFixed(instr->value(), rax);
- LToFastProperties* result = new LToFastProperties(object);
+ LToFastProperties* result = new(zone()) LToFastProperties(object);
return MarkAsCall(DefineFixed(result, rax), instr);
}
LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
- LTypeof* result = new LTypeof(UseAtStart(instr->value()));
+ LTypeof* result = new(zone()) LTypeof(UseAtStart(instr->value()));
return MarkAsCall(DefineFixed(result, rax), instr);
}
LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
- return new LTypeofIsAndBranch(UseTempRegister(instr->value()));
+ return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
}
LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
HIsConstructCallAndBranch* instr) {
- return new LIsConstructCallAndBranch(TempRegister());
+ return new(zone()) LIsConstructCallAndBranch(TempRegister());
}
@@ -2224,7 +2250,7 @@
// 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()) {
- LLazyBailout* lazy_bailout = new LLazyBailout;
+ LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
LInstruction* result = AssignEnvironment(lazy_bailout);
instruction_pending_deoptimization_environment_->
set_deoptimization_environment(result->environment());
@@ -2238,10 +2264,10 @@
LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
if (instr->is_function_entry()) {
- return MarkAsCall(new LStackCheck, instr);
+ return MarkAsCall(new(zone()) LStackCheck, instr);
} else {
ASSERT(instr->is_backwards_branch());
- return AssignEnvironment(AssignPointerMap(new LStackCheck));
+ return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
}
}
@@ -2272,14 +2298,14 @@
LInstruction* LChunkBuilder::DoIn(HIn* instr) {
LOperand* key = UseOrConstantAtStart(instr->key());
LOperand* object = UseOrConstantAtStart(instr->object());
- LIn* result = new LIn(key, object);
+ LIn* result = new(zone()) LIn(key, object);
return MarkAsCall(DefineFixed(result, rax), instr);
}
LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
LOperand* object = UseFixed(instr->enumerable(), rax);
- LForInPrepareMap* result = new LForInPrepareMap(object);
+ LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
}
@@ -2287,21 +2313,21 @@
LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
LOperand* map = UseRegister(instr->map());
return AssignEnvironment(DefineAsRegister(
- new LForInCacheArray(map)));
+ new(zone()) LForInCacheArray(map)));
}
LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
LOperand* map = UseRegisterAtStart(instr->map());
- return AssignEnvironment(new LCheckMapValue(value, map));
+ return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
}
LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
LOperand* object = UseRegister(instr->object());
LOperand* index = UseTempRegister(instr->index());
- return DefineSameAsFirst(new LLoadFieldByIndex(object, index));
+ return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
}
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index b8a8c8a..d848c44 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -2181,6 +2181,7 @@
: chunk_(NULL),
info_(info),
graph_(graph),
+ zone_(graph->isolate()->zone()),
status_(UNUSED),
current_instruction_(NULL),
current_block_(NULL),
@@ -2210,6 +2211,7 @@
LChunk* chunk() const { return chunk_; }
CompilationInfo* info() const { return info_; }
HGraph* graph() const { return graph_; }
+ Zone* zone() const { return zone_; }
bool is_unused() const { return status_ == UNUSED; }
bool is_building() const { return status_ == BUILDING; }
@@ -2318,6 +2320,7 @@
LChunk* chunk_;
CompilationInfo* info_;
HGraph* const graph_;
+ Zone* zone_;
Status status_;
HInstruction* current_instruction_;
HBasicBlock* current_block_;
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 16730d2..773fc4c 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -1192,7 +1192,7 @@
ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size());
- MaybeObject* result = Execution::HandleStackGuardInterrupt();
+ MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
if (*code_handle != re_code) { // Return address no longer valid
intptr_t delta = code_handle->address() - re_code->address();
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 0e7f206..18cb3c0 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -43,32 +43,61 @@
MacroAssembler* masm,
Code::Flags flags,
StubCache::Table table,
+ Register receiver,
Register name,
+ // The offset is scaled by 4, based on
+ // kHeapObjectTagSize, which is two bits
Register offset) {
- ASSERT_EQ(8, kPointerSize);
- ASSERT_EQ(16, sizeof(StubCache::Entry));
+ // We need to scale up the pointer by 2 because the offset is scaled by less
+ // than the pointer size.
+ ASSERT(kPointerSizeLog2 == kHeapObjectTagSize + 1);
+ ScaleFactor scale_factor = times_2;
+
+ ASSERT_EQ(24, sizeof(StubCache::Entry));
// The offset register holds the entry offset times four (due to masking
// and shifting optimizations).
ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
+ ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
Label miss;
+ // Multiply by 3 because there are 3 fields per entry (name, code, map).
+ __ lea(offset, Operand(offset, offset, times_2, 0));
+
__ LoadAddress(kScratchRegister, key_offset);
+
// Check that the key in the entry matches the name.
// Multiply entry offset by 16 to get the entry address. Since the
// offset register already holds the entry offset times four, multiply
// by a further four.
- __ cmpl(name, Operand(kScratchRegister, offset, times_4, 0));
+ __ cmpl(name, Operand(kScratchRegister, offset, scale_factor, 0));
__ j(not_equal, &miss);
- // Get the code entry from the cache.
- // Use key_offset + kPointerSize, rather than loading value_offset.
+
+ // Get the map entry from the cache.
+ // Use key_offset + kPointerSize * 2, rather than loading map_offset.
__ movq(kScratchRegister,
- Operand(kScratchRegister, offset, times_4, kPointerSize));
+ Operand(kScratchRegister, offset, scale_factor, kPointerSize * 2));
+ __ cmpq(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ j(not_equal, &miss);
+
+ // Get the code entry from the cache.
+ __ LoadAddress(kScratchRegister, value_offset);
+ __ movq(kScratchRegister,
+ Operand(kScratchRegister, offset, scale_factor, 0));
+
// Check that the flags match what we're looking for.
__ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
__ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
__ cmpl(offset, Immediate(flags));
__ j(not_equal, &miss);
+#ifdef DEBUG
+ if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
+ __ jmp(&miss);
+ } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
+ __ jmp(&miss);
+ }
+#endif
+
// Jump to the first instruction in the code stub.
__ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(kScratchRegister);
@@ -134,14 +163,16 @@
Register name,
Register scratch,
Register extra,
- Register extra2) {
+ Register extra2,
+ Register extra3) {
Isolate* isolate = masm->isolate();
Label miss;
USE(extra); // The register extra is not used on the X64 platform.
USE(extra2); // The register extra2 is not used on the X64 platform.
- // Make sure that code is valid. The shifting code relies on the
- // entry size being 16.
- ASSERT(sizeof(Entry) == 16);
+ USE(extra3); // The register extra2 is not used on the X64 platform.
+ // Make sure that code is valid. The multiplying code relies on the
+ // entry size being 24.
+ ASSERT(sizeof(Entry) == 24);
// Make sure the flags do not name a specific type.
ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
@@ -153,6 +184,10 @@
// Check scratch register is valid, extra and extra2 are unused.
ASSERT(!scratch.is(no_reg));
ASSERT(extra2.is(no_reg));
+ ASSERT(extra3.is(no_reg));
+
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
// Check that the receiver isn't a smi.
__ JumpIfSmi(receiver, &miss);
@@ -162,10 +197,12 @@
// Use only the low 32 bits of the map pointer.
__ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ xor_(scratch, Immediate(flags));
+ // We mask out the last two bits because they are not part of the hash and
+ // they are always 01 for maps. Also in the two 'and' instructions below.
__ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
// Probe the primary table.
- ProbeTable(isolate, masm, flags, kPrimary, name, scratch);
+ ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch);
// Primary miss: Compute hash for secondary probe.
__ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
@@ -177,11 +214,12 @@
__ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
// Probe the secondary table.
- ProbeTable(isolate, masm, flags, kSecondary, name, scratch);
+ ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.
__ bind(&miss);
+ __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index a7e45d1..641c443 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -12910,7 +12910,7 @@
if (array_type == v8::kExternalDoubleArray ||
array_type == v8::kExternalFloatArray) {
CHECK_EQ(
- static_cast<int>(0x80000000),
+ static_cast<int>(i::OS::nan_value()),
static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
} else {
CHECK_EQ(0, static_cast<int>(
@@ -16102,3 +16102,72 @@
v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
CompileRun("throw 'first exception';");
}
+
+
+static int probes_counter = 0;
+static int misses_counter = 0;
+static int updates_counter = 0;
+
+
+static int* LookupCounter(const char* name) {
+ if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
+ return &probes_counter;
+ } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
+ return &misses_counter;
+ } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
+ return &updates_counter;
+ }
+ return NULL;
+}
+
+
+static const char* kMegamorphicTestProgram =
+ "function ClassA() { };"
+ "function ClassB() { };"
+ "ClassA.prototype.foo = function() { };"
+ "ClassB.prototype.foo = function() { };"
+ "function fooify(obj) { obj.foo(); };"
+ "var a = new ClassA();"
+ "var b = new ClassB();"
+ "for (var i = 0; i < 10000; i++) {"
+ " fooify(a);"
+ " fooify(b);"
+ "}";
+
+
+static void StubCacheHelper(bool primary) {
+ V8::SetCounterFunction(LookupCounter);
+ USE(kMegamorphicTestProgram);
+#ifdef DEBUG
+ i::FLAG_native_code_counters = true;
+ if (primary) {
+ i::FLAG_test_primary_stub_cache = true;
+ } else {
+ i::FLAG_test_secondary_stub_cache = true;
+ }
+ i::FLAG_crankshaft = false;
+ v8::HandleScope scope;
+ LocalContext env;
+ int initial_probes = probes_counter;
+ int initial_misses = misses_counter;
+ int initial_updates = updates_counter;
+ CompileRun(kMegamorphicTestProgram);
+ int probes = probes_counter - initial_probes;
+ int misses = misses_counter - initial_misses;
+ int updates = updates_counter - initial_updates;
+ CHECK_LT(updates, 10);
+ CHECK_LT(misses, 10);
+ CHECK_GE(probes, 10000);
+#endif
+}
+
+
+TEST(SecondaryStubCache) {
+ StubCacheHelper(true);
+}
+
+
+TEST(PrimaryStubCache) {
+ StubCacheHelper(false);
+}
+
diff --git a/test/mjsunit/harmony/module-parsing.js b/test/mjsunit/harmony/module-parsing.js
index 5a5e82f..cf56502 100644
--- a/test/mjsunit/harmony/module-parsing.js
+++ b/test/mjsunit/harmony/module-parsing.js
@@ -36,19 +36,39 @@
module A3 = A2
module B {
- var x
- var x, y;
- var x = 0, y
- let x, y
- let z = 1
+ export x
+ export y, z, c, f
+
+ var vx
+ var vx, vy;
+ var vx = 0, vy
+ let lx, ly
+ let lz = 1
const c = 9
function f() {}
+
module C {
let x
module D {}
let y
}
+
let zz = ""
+
+ export var x0
+ export var x1, x2 = 6, x3
+ export let y0
+ export let y1 = 0, y2
+ export const z0 = 0
+ export const z1 = 2, z2 = 3
+ export function f0() {}
+ export module M1 {}
+ export module M2 = C.D
+ export module M3 at "http://where"
+
+ import i0 from I
+ import i1, i2, i3 from I
+ import i4, i5 from "http://where"
}
module C1 = B.C;
@@ -76,6 +96,45 @@
at
"file://local"
+import
+x
+,
+y
+from
+"file://local"
+
+module Wrap {
+export
+x
+,
+y
+
+export
+var
+v1 = 1
+
+export
+let
+v2 = 2
+
+export
+const
+v3 = 3
+
+export
+function
+f
+(
+)
+{
+}
+
+export
+module V
+{
+}
+}
+
// Check that 'module' still works as an identifier.
diff --git a/test/test262/test262.status b/test/test262/test262.status
index 4d82418..16a478b 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -48,12 +48,12 @@
# octal numbers in order to not break the web.
S15.1.2.2_A5.1_T1: FAIL_OK
-# This tests precision of trignometric functions. We're slightly off
-# from the implementation in libc (~ 1e-17) but it's not clear if we
-# or they are closer to the right answer, or if it even matters.
+# This tests precision of Math.tan and Math.sin. The implementation for those
+# trigonometric functions are platform/compiler dependent. Furthermore, the
+# expectation values by far deviates from the actual result given by an
+# arbitrary-precision calculator, making those tests partly bogus.
S15.8.2.16_A7: PASS || FAIL_OK
S15.8.2.18_A7: PASS || FAIL_OK
-S15.8.2.13_A23: PASS || FAIL_OK
# We are more lenient in which string character escapes we allow than
# the spec (7.8.4 p. 19) wants us to be. This is for compatibility.