}
+XMMRegister LCodeGen::ToSIMD128Register(int index) const {
+ return XMMRegister::FromAllocationIndex(index);
+}
+
+
Register LCodeGen::ToRegister(LOperand* op) const {
ASSERT(op->IsRegister());
return ToRegister(op->index());
}
+XMMRegister LCodeGen::ToFloat32x4Register(LOperand* op) const {
+ ASSERT(op->IsFloat32x4Register());
+ return ToSIMD128Register(op->index());
+}
+
+
+XMMRegister LCodeGen::ToInt32x4Register(LOperand* op) const {
+ ASSERT(op->IsInt32x4Register());
+ return ToSIMD128Register(op->index());
+}
+
+
+XMMRegister LCodeGen::ToSIMD128Register(LOperand* op) const {
+ ASSERT(op->IsFloat32x4Register() || op->IsInt32x4Register());
+ return ToSIMD128Register(op->index());
+}
+
+
bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const {
return op->IsConstantOperand() &&
chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
Operand LCodeGen::ToOperand(LOperand* op) const {
// Does not handle registers. In X64 assembler, plain registers are not
// representable as an Operand.
- ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
+ ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot() ||
+ op->IsFloat32x4StackSlot() || op->IsInt32x4StackSlot());
if (NeedsEagerFrame()) {
return Operand(rbp, StackSlotOffset(op->index()));
} else {
}
} else if (op->IsDoubleStackSlot()) {
translation->StoreDoubleStackSlot(op->index());
+ } else if (op->IsFloat32x4StackSlot()) {
+ translation->StoreSIMD128StackSlot(op->index(),
+ Translation::FLOAT32x4_STACK_SLOT);
+ } else if (op->IsInt32x4StackSlot()) {
+ translation->StoreSIMD128StackSlot(op->index(),
+ Translation::INT32x4_STACK_SLOT);
} else if (op->IsArgument()) {
ASSERT(is_tagged);
int src_index = GetStackSlotCount() + op->index();
} else if (op->IsDoubleRegister()) {
XMMRegister reg = ToDoubleRegister(op);
translation->StoreDoubleRegister(reg);
+ } else if (op->IsFloat32x4Register()) {
+ XMMRegister reg = ToFloat32x4Register(op);
+ translation->StoreSIMD128Register(reg, Translation::FLOAT32x4_REGISTER);
+ } else if (op->IsInt32x4Register()) {
+ XMMRegister reg = ToInt32x4Register(op);
+ translation->StoreSIMD128Register(reg, Translation::INT32x4_REGISTER);
} else if (op->IsConstantOperand()) {
HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
ASSERT(ToRegister(instr->context()).is(rsi));
ASSERT(ToRegister(instr->result()).is(rax));
switch (instr->hydrogen()->major_key()) {
- case CodeStub::RegExpConstructResult: {
- RegExpConstructResultStub stub;
- CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
- break;
- }
case CodeStub::RegExpExec: {
RegExpExecStub stub;
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
}
-void LCodeGen::DoElementsKind(LElementsKind* instr) {
- Register result = ToRegister(instr->result());
- Register input = ToRegister(instr->value());
-
- // Load map into |result|.
- __ movp(result, FieldOperand(input, HeapObject::kMapOffset));
- // Load the map's "bit field 2" into |result|. We only need the first byte.
- __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset));
- // Retrieve elements_kind from bit field 2.
- __ and_(result, Immediate(Map::kElementsKindMask));
- __ shr(result, Immediate(Map::kElementsKindShift));
-}
-
-
-void LCodeGen::DoValueOf(LValueOf* instr) {
- Register input = ToRegister(instr->value());
- Register result = ToRegister(instr->result());
- ASSERT(input.is(result));
- Label done;
-
- if (!instr->hydrogen()->value()->IsHeapObject()) {
- // If the object is a smi return the object.
- __ JumpIfSmi(input, &done, Label::kNear);
- }
-
- // If the object is not a value type, return the object.
- __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister);
- __ j(not_equal, &done, Label::kNear);
- __ movp(result, FieldOperand(input, JSValue::kValueOffset));
-
- __ bind(&done);
-}
-
-
void LCodeGen::DoDateField(LDateField* instr) {
Register object = ToRegister(instr->date());
Register result = ToRegister(instr->result());
}
-void LCodeGen::DoThrow(LThrow* instr) {
- __ push(ToRegister(instr->value()));
- ASSERT(ToRegister(instr->context()).is(rsi));
- CallRuntime(Runtime::kThrow, 1, instr);
-
- if (FLAG_debug_code) {
- Comment("Unreachable code.");
- __ int3();
- }
-}
-
-
void LCodeGen::DoAddI(LAddI* instr) {
LOperand* left = instr->left();
LOperand* right = instr->right();
}
Register object = ToRegister(instr->object());
- if (FLAG_track_double_fields &&
- instr->hydrogen()->representation().IsDouble()) {
+ if (instr->hydrogen()->representation().IsDouble()) {
XMMRegister result = ToDoubleRegister(instr->result());
__ movsd(result, FieldOperand(object, offset));
return;
}
-void LCodeGen::DoLoadExternalArrayPointer(
- LLoadExternalArrayPointer* instr) {
- Register result = ToRegister(instr->result());
- Register input = ToRegister(instr->object());
- __ movp(result,
- FieldOperand(input,
- ExternalUint8ClampedArray::kExternalPointerOffset));
-}
-
-
void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
Register arguments = ToRegister(instr->arguments());
Register result = ToRegister(instr->result());
}
+void LCodeGen::HandleExternalArrayOpRequiresPreScale(
+ LOperand* key,
+ ElementsKind elements_kind) {
+ if (ExternalArrayOpRequiresPreScale(elements_kind)) {
+ int pre_shift_size = ElementsKindToShiftSize(elements_kind) -
+ static_cast<int>(maximal_scale_factor);
+ ASSERT(pre_shift_size > 0);
+ __ shl(ToRegister(key), Immediate(pre_shift_size));
+ }
+}
+
+
void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
+
+ HandleExternalArrayOpRequiresPreScale(key, elements_kind);
}
int base_offset = instr->is_fixed_typed_array()
? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
} else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
elements_kind == FLOAT64_ELEMENTS) {
__ movsd(ToDoubleRegister(instr->result()), operand);
+ } else if (IsSIMD128ElementsKind(elements_kind)) {
+ __ movups(ToSIMD128Register(instr->result()), operand);
} else {
Register result(ToRegister(instr->result()));
switch (elements_kind) {
break;
case EXTERNAL_FLOAT32_ELEMENTS:
case EXTERNAL_FLOAT64_ELEMENTS:
+ case EXTERNAL_FLOAT32x4_ELEMENTS:
+ case EXTERNAL_INT32x4_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
+ case FLOAT32x4_ELEMENTS:
+ case INT32x4_ELEMENTS:
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
if (constant_value & 0xF0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
+
return Operand(elements_pointer_reg,
((constant_value + additional_index) << shift_size)
+ offset);
} else {
+ if (ExternalArrayOpRequiresPreScale(elements_kind)) {
+ // Make sure the key is pre-scaled against maximal_scale_factor.
+ shift_size = static_cast<int>(maximal_scale_factor);
+ }
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
return Operand(elements_pointer_reg,
ToRegister(key),
Label global_object, receiver_ok;
Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
- // Do not transform the receiver to object for strict mode
- // functions.
- __ movp(kScratchRegister,
- FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
- __ testb(FieldOperand(kScratchRegister,
- SharedFunctionInfo::kStrictModeByteOffset),
- Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
- __ j(not_equal, &receiver_ok, dist);
-
- // Do not transform the receiver to object for builtins.
- __ testb(FieldOperand(kScratchRegister,
- SharedFunctionInfo::kNativeByteOffset),
- Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
- __ j(not_equal, &receiver_ok, dist);
+ if (!instr->hydrogen()->known_function()) {
+ // Do not transform the receiver to object for strict mode
+ // functions.
+ __ movp(kScratchRegister,
+ FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
+ __ testb(FieldOperand(kScratchRegister,
+ SharedFunctionInfo::kStrictModeByteOffset),
+ Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
+ __ j(not_equal, &receiver_ok, dist);
+
+ // Do not transform the receiver to object for builtins.
+ __ testb(FieldOperand(kScratchRegister,
+ SharedFunctionInfo::kNativeByteOffset),
+ Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
+ __ j(not_equal, &receiver_ok, dist);
+ }
// Normal function. Replace undefined or null with global receiver.
__ CompareRoot(receiver, Heap::kNullValueRootIndex);
DeoptimizeIf(is_smi, instr->environment());
__ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
DeoptimizeIf(below, instr->environment());
- __ jmp(&receiver_ok, Label::kNear);
+ __ jmp(&receiver_ok, Label::kNear);
__ bind(&global_object);
__ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
__ movp(receiver,
- Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+ Operand(receiver,
+ Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ movp(receiver,
FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset));
+
__ bind(&receiver_ok);
}
}
-void LCodeGen::DoOuterContext(LOuterContext* instr) {
- Register context = ToRegister(instr->context());
- Register result = ToRegister(instr->result());
- __ movp(result,
- Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
-}
-
-
void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
ASSERT(ToRegister(instr->context()).is(rsi));
__ push(rsi); // The context is the first argument.
}
-void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
- Register context = ToRegister(instr->context());
- Register result = ToRegister(instr->result());
- __ movp(result,
- Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
-}
-
-
-void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
- Register global = ToRegister(instr->global());
- Register result = ToRegister(instr->result());
- __ movp(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset));
-}
-
-
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
__ LoadFromSafepointRegisterSlot(input_reg, input_reg);
__ bind(&allocated);
- __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
+ __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ shl(tmp2, Immediate(1));
__ shr(tmp2, Immediate(1));
- __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
+ __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
__ StoreToSafepointRegisterSlot(input_reg, tmp);
__ bind(&done);
}
+void LCodeGen::DoNullarySIMDOperation(LNullarySIMDOperation* instr) {
+ switch (instr->op()) {
+ case kFloat32x4Zero: {
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ __ xorps(result_reg, result_reg);
+ return;
+ }
+ case kInt32x4Zero: {
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ __ xorps(result_reg, result_reg);
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoUnarySIMDOperation(LUnarySIMDOperation* instr) {
+ uint8_t select = 0;
+ switch (instr->op()) {
+ case kSIMD128Change: {
+ Comment(";;; deoptimize: can not perform representation change"
+ "for float32x4 or int32x4");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ case kFloat32x4Abs:
+ case kFloat32x4Neg:
+ case kFloat32x4Reciprocal:
+ case kFloat32x4ReciprocalSqrt:
+ case kFloat32x4Sqrt: {
+ ASSERT(instr->value()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ switch (instr->op()) {
+ case kFloat32x4Abs:
+ __ absps(input_reg);
+ break;
+ case kFloat32x4Neg:
+ __ negateps(input_reg);
+ break;
+ case kFloat32x4Reciprocal:
+ __ rcpps(input_reg, input_reg);
+ break;
+ case kFloat32x4ReciprocalSqrt:
+ __ rsqrtps(input_reg, input_reg);
+ break;
+ case kFloat32x4Sqrt:
+ __ sqrtps(input_reg, input_reg);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kInt32x4Not:
+ case kInt32x4Neg: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ switch (instr->op()) {
+ case kInt32x4Not:
+ __ notps(input_reg);
+ break;
+ case kInt32x4Neg:
+ __ pnegd(input_reg);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kFloat32x4BitsToInt32x4:
+ case kFloat32x4ToInt32x4: {
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ if (instr->op() == kFloat32x4BitsToInt32x4) {
+ if (!result_reg.is(input_reg)) {
+ __ movaps(result_reg, input_reg);
+ }
+ } else {
+ ASSERT(instr->op() == kFloat32x4ToInt32x4);
+ __ cvtps2dq(result_reg, input_reg);
+ }
+ return;
+ }
+ case kInt32x4BitsToFloat32x4:
+ case kInt32x4ToFloat32x4: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ if (instr->op() == kInt32x4BitsToFloat32x4) {
+ if (!result_reg.is(input_reg)) {
+ __ movaps(result_reg, input_reg);
+ }
+ } else {
+ ASSERT(instr->op() == kInt32x4ToFloat32x4);
+ __ cvtdq2ps(result_reg, input_reg);
+ }
+ return;
+ }
+ case kFloat32x4Splat: {
+ ASSERT(instr->hydrogen()->value()->representation().IsDouble());
+ XMMRegister input_reg = ToDoubleRegister(instr->value());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ XMMRegister xmm_scratch = xmm0;
+ __ xorps(xmm_scratch, xmm_scratch);
+ __ cvtsd2ss(xmm_scratch, input_reg);
+ __ shufps(xmm_scratch, xmm_scratch, 0x0);
+ __ movaps(result_reg, xmm_scratch);
+ return;
+ }
+ case kInt32x4Splat: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+ Register input_reg = ToRegister(instr->value());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ __ movd(result_reg, input_reg);
+ __ shufps(result_reg, result_reg, 0x0);
+ return;
+ }
+ case kInt32x4GetSignMask: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ Register result = ToRegister(instr->result());
+ __ movmskps(result, input_reg);
+ return;
+ }
+ case kFloat32x4GetSignMask: {
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ Register result = ToRegister(instr->result());
+ __ movmskps(result, input_reg);
+ return;
+ }
+ case kFloat32x4GetW:
+ select++;
+ case kFloat32x4GetZ:
+ select++;
+ case kFloat32x4GetY:
+ select++;
+ case kFloat32x4GetX: {
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ XMMRegister result = ToDoubleRegister(instr->result());
+ XMMRegister xmm_scratch = result.is(input_reg) ? xmm0 : result;
+
+ if (select == 0x0) {
+ __ xorps(xmm_scratch, xmm_scratch);
+ __ cvtss2sd(xmm_scratch, input_reg);
+ if (!xmm_scratch.is(result)) {
+ __ movaps(result, xmm_scratch);
+ }
+ } else {
+ __ pshufd(xmm_scratch, input_reg, select);
+ if (!xmm_scratch.is(result)) {
+ __ xorps(result, result);
+ }
+ __ cvtss2sd(result, xmm_scratch);
+ }
+ return;
+ }
+ case kInt32x4GetX:
+ case kInt32x4GetY:
+ case kInt32x4GetZ:
+ case kInt32x4GetW:
+ case kInt32x4GetFlagX:
+ case kInt32x4GetFlagY:
+ case kInt32x4GetFlagZ:
+ case kInt32x4GetFlagW: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ bool flag = false;
+ switch (instr->op()) {
+ case kInt32x4GetFlagX:
+ flag = true;
+ case kInt32x4GetX:
+ break;
+ case kInt32x4GetFlagY:
+ flag = true;
+ case kInt32x4GetY:
+ select = 0x1;
+ break;
+ case kInt32x4GetFlagZ:
+ flag = true;
+ case kInt32x4GetZ:
+ select = 0x2;
+ break;
+ case kInt32x4GetFlagW:
+ flag = true;
+ case kInt32x4GetW:
+ select = 0x3;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ Register result = ToRegister(instr->result());
+ if (select == 0x0) {
+ __ movd(result, input_reg);
+ } else {
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ extractps(result, input_reg, select);
+ } else {
+ XMMRegister xmm_scratch = xmm0;
+ __ pshufd(xmm_scratch, input_reg, select);
+ __ movd(result, xmm_scratch);
+ }
+ }
+
+ if (flag) {
+ Label false_value, done;
+ __ testl(result, result);
+ __ j(zero, &false_value, Label::kNear);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+ __ jmp(&done, Label::kNear);
+ __ bind(&false_value);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ bind(&done);
+ }
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoBinarySIMDOperation(LBinarySIMDOperation* instr) {
+ uint8_t imm8 = 0; // for with operation
+ switch (instr->op()) {
+ case kFloat32x4Add:
+ case kFloat32x4Sub:
+ case kFloat32x4Mul:
+ case kFloat32x4Div:
+ case kFloat32x4Min:
+ case kFloat32x4Max: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToFloat32x4Register(instr->right());
+ switch (instr->op()) {
+ case kFloat32x4Add:
+ __ addps(left_reg, right_reg);
+ break;
+ case kFloat32x4Sub:
+ __ subps(left_reg, right_reg);
+ break;
+ case kFloat32x4Mul:
+ __ mulps(left_reg, right_reg);
+ break;
+ case kFloat32x4Div:
+ __ divps(left_reg, right_reg);
+ break;
+ case kFloat32x4Min:
+ __ minps(left_reg, right_reg);
+ break;
+ case kFloat32x4Max:
+ __ maxps(left_reg, right_reg);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kFloat32x4Scale: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsDouble());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToDoubleRegister(instr->right());
+ XMMRegister scratch_reg = xmm0;
+ __ xorps(scratch_reg, scratch_reg);
+ __ cvtsd2ss(scratch_reg, right_reg);
+ __ shufps(scratch_reg, scratch_reg, 0x0);
+ __ mulps(left_reg, scratch_reg);
+ return;
+ }
+ case kFloat32x4Shuffle: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ if (instr->hydrogen()->right()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
+ uint8_t select = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ __ shufps(left_reg, left_reg, select);
+ return;
+ } else {
+ Comment(";;; deoptimize: non-constant selector for shuffle");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ }
+ case kInt32x4Shuffle: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ if (instr->hydrogen()->right()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
+ uint8_t select = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ __ pshufd(left_reg, left_reg, select);
+ return;
+ } else {
+ Comment(";;; deoptimize: non-constant selector for shuffle");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ }
+ case kInt32x4ShiftLeft:
+ case kInt32x4ShiftRight:
+ case kInt32x4ShiftRightArithmetic: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ if (instr->hydrogen()->right()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
+ uint8_t shift = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ switch (instr->op()) {
+ case kInt32x4ShiftLeft:
+ __ pslld(left_reg, shift);
+ break;
+ case kInt32x4ShiftRight:
+ __ psrld(left_reg, shift);
+ break;
+ case kInt32x4ShiftRightArithmetic:
+ __ psrad(left_reg, shift);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return;
+ } else {
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ Register shift = ToRegister(instr->right());
+ XMMRegister xmm_scratch = double_scratch0();
+ __ movd(xmm_scratch, shift);
+ switch (instr->op()) {
+ case kInt32x4ShiftLeft:
+ __ pslld(left_reg, xmm_scratch);
+ break;
+ case kInt32x4ShiftRight:
+ __ psrld(left_reg, xmm_scratch);
+ break;
+ case kInt32x4ShiftRightArithmetic:
+ __ psrad(left_reg, xmm_scratch);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return;
+ }
+ }
+ case kFloat32x4LessThan:
+ case kFloat32x4LessThanOrEqual:
+ case kFloat32x4Equal:
+ case kFloat32x4NotEqual:
+ case kFloat32x4GreaterThanOrEqual:
+ case kFloat32x4GreaterThan: {
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToFloat32x4Register(instr->right());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ switch (instr->op()) {
+ case kFloat32x4LessThan:
+ if (result_reg.is(left_reg)) {
+ __ cmpltps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpnltps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpltps(result_reg, right_reg);
+ }
+ break;
+ case kFloat32x4LessThanOrEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpleps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpnleps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpleps(result_reg, right_reg);
+ }
+ break;
+ case kFloat32x4Equal:
+ if (result_reg.is(left_reg)) {
+ __ cmpeqps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpeqps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpeqps(result_reg, right_reg);
+ }
+ break;
+ case kFloat32x4NotEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpneqps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpneqps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpneqps(result_reg, right_reg);
+ }
+ break;
+ case kFloat32x4GreaterThanOrEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpnltps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpltps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpnltps(result_reg, right_reg);
+ }
+ break;
+ case kFloat32x4GreaterThan:
+ if (result_reg.is(left_reg)) {
+ __ cmpnleps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpleps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpnleps(result_reg, right_reg);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kInt32x4And:
+ case kInt32x4Or:
+ case kInt32x4Xor:
+ case kInt32x4Add:
+ case kInt32x4Sub:
+ case kInt32x4Mul:
+ case kInt32x4GreaterThan:
+ case kInt32x4Equal:
+ case kInt32x4LessThan: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsInt32x4());
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ XMMRegister right_reg = ToInt32x4Register(instr->right());
+ switch (instr->op()) {
+ case kInt32x4And:
+ __ andps(left_reg, right_reg);
+ break;
+ case kInt32x4Or:
+ __ orps(left_reg, right_reg);
+ break;
+ case kInt32x4Xor:
+ __ xorps(left_reg, right_reg);
+ break;
+ case kInt32x4Add:
+ __ paddd(left_reg, right_reg);
+ break;
+ case kInt32x4Sub:
+ __ psubd(left_reg, right_reg);
+ break;
+ case kInt32x4Mul:
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ pmulld(left_reg, right_reg);
+ } else {
+ // The algorithm is from http://stackoverflow.com/questions/10500766/sse-multiplication-of-4-32-bit-integers
+ XMMRegister xmm_scratch = xmm0;
+ __ movaps(xmm_scratch, left_reg);
+ __ pmuludq(left_reg, right_reg);
+ __ psrldq(xmm_scratch, 4);
+ __ psrldq(right_reg, 4);
+ __ pmuludq(xmm_scratch, right_reg);
+ __ pshufd(left_reg, left_reg, 8);
+ __ pshufd(xmm_scratch, xmm_scratch, 8);
+ __ punpackldq(left_reg, xmm_scratch);
+ }
+ break;
+ case kInt32x4GreaterThan:
+ __ pcmpgtd(left_reg, right_reg);
+ break;
+ case kInt32x4Equal:
+ __ pcmpeqd(left_reg, right_reg);
+ break;
+ case kInt32x4LessThan: {
+ XMMRegister xmm_scratch = xmm0;
+ __ movaps(xmm_scratch, right_reg);
+ __ pcmpgtd(xmm_scratch, left_reg);
+ __ movaps(left_reg, xmm_scratch);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kFloat32x4WithW:
+ imm8++;
+ case kFloat32x4WithZ:
+ imm8++;
+ case kFloat32x4WithY:
+ imm8++;
+ case kFloat32x4WithX: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsDouble());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToDoubleRegister(instr->right());
+ XMMRegister xmm_scratch = xmm0;
+ __ xorps(xmm_scratch, xmm_scratch);
+ __ cvtsd2ss(xmm_scratch, right_reg);
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ imm8 = imm8 << 4;
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ insertps(left_reg, xmm_scratch, imm8);
+ } else {
+ __ subq(rsp, Immediate(kFloat32x4Size));
+ __ movups(Operand(rsp, 0), left_reg);
+ __ movss(Operand(rsp, imm8 * kFloatSize), xmm_scratch);
+ __ movups(left_reg, Operand(rsp, 0));
+ __ addq(rsp, Immediate(kFloat32x4Size));
+ }
+ return;
+ }
+ case kInt32x4WithW:
+ imm8++;
+ case kInt32x4WithZ:
+ imm8++;
+ case kInt32x4WithY:
+ imm8++;
+ case kInt32x4WithX: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsInteger32());
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ Register right_reg = ToRegister(instr->right());
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ pinsrd(left_reg, right_reg, imm8);
+ } else {
+ __ subq(rsp, Immediate(kInt32x4Size));
+ __ movdqu(Operand(rsp, 0), left_reg);
+ __ movl(Operand(rsp, imm8 * kFloatSize), right_reg);
+ __ movdqu(left_reg, Operand(rsp, 0));
+ __ addq(rsp, Immediate(kInt32x4Size));
+ }
+ return;
+ }
+ case kInt32x4WithFlagW:
+ imm8++;
+ case kInt32x4WithFlagZ:
+ imm8++;
+ case kInt32x4WithFlagY:
+ imm8++;
+ case kInt32x4WithFlagX: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsTagged());
+ HType type = instr->hydrogen()->right()->type();
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ Register right_reg = ToRegister(instr->right());
+ Label load_false_value, done;
+ if (type.IsBoolean()) {
+ __ subq(rsp, Immediate(kInt32x4Size));
+ __ movups(Operand(rsp, 0), left_reg);
+ __ CompareRoot(right_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_value, Label::kNear);
+ } else {
+ Comment(";;; deoptimize: other types for int32x4.withFlagX/Y/Z/W.");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ // load true value.
+ __ movl(Operand(rsp, imm8 * kFloatSize), Immediate(0xFFFFFFFF));
+ __ jmp(&done, Label::kNear);
+ __ bind(&load_false_value);
+ __ movl(Operand(rsp, imm8 * kFloatSize), Immediate(0x0));
+ __ bind(&done);
+ __ movups(left_reg, Operand(rsp, 0));
+ __ addq(rsp, Immediate(kInt32x4Size));
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoTernarySIMDOperation(LTernarySIMDOperation* instr) {
+ switch (instr->op()) {
+ case kInt32x4Select: {
+ ASSERT(instr->hydrogen()->first()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
+
+ XMMRegister mask_reg = ToInt32x4Register(instr->first());
+ XMMRegister left_reg = ToFloat32x4Register(instr->second());
+ XMMRegister right_reg = ToFloat32x4Register(instr->third());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ XMMRegister temp_reg = xmm0;
+
+ // Copy mask.
+ __ movaps(temp_reg, mask_reg);
+ // Invert it.
+ __ notps(temp_reg);
+ // temp_reg = temp_reg & falseValue.
+ __ andps(temp_reg, right_reg);
+
+ if (!result_reg.is(mask_reg)) {
+ if (result_reg.is(left_reg)) {
+ // result_reg = result_reg & trueValue.
+ __ andps(result_reg, mask_reg);
+ // out = result_reg | temp_reg.
+ __ orps(result_reg, temp_reg);
+ } else {
+ __ movaps(result_reg, mask_reg);
+ // result_reg = result_reg & trueValue.
+ __ andps(result_reg, left_reg);
+ // out = result_reg | temp_reg.
+ __ orps(result_reg, temp_reg);
+ }
+ } else {
+ // result_reg = result_reg & trueValue.
+ __ andps(result_reg, left_reg);
+ // out = result_reg | temp_reg.
+ __ orps(result_reg, temp_reg);
+ }
+ return;
+ }
+ case kFloat32x4ShuffleMix: {
+ ASSERT(instr->first()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->third()->representation().IsInteger32());
+ if (instr->hydrogen()->third()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->third())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->third()));
+ uint8_t select = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister first_reg = ToFloat32x4Register(instr->first());
+ XMMRegister second_reg = ToFloat32x4Register(instr->second());
+ __ shufps(first_reg, second_reg, select);
+ return;
+ } else {
+ Comment(";;; deoptimize: non-constant selector for shuffle");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ }
+ case kFloat32x4Clamp: {
+ ASSERT(instr->first()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
+
+ XMMRegister value_reg = ToFloat32x4Register(instr->first());
+ XMMRegister lower_reg = ToFloat32x4Register(instr->second());
+ XMMRegister upper_reg = ToFloat32x4Register(instr->third());
+ __ minps(value_reg, upper_reg);
+ __ maxps(value_reg, lower_reg);
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoQuarternarySIMDOperation(LQuarternarySIMDOperation* instr) {
+ switch (instr->op()) {
+ case kFloat32x4Constructor: {
+ ASSERT(instr->hydrogen()->x()->representation().IsDouble());
+ ASSERT(instr->hydrogen()->y()->representation().IsDouble());
+ ASSERT(instr->hydrogen()->z()->representation().IsDouble());
+ ASSERT(instr->hydrogen()->w()->representation().IsDouble());
+ XMMRegister x_reg = ToDoubleRegister(instr->x());
+ XMMRegister y_reg = ToDoubleRegister(instr->y());
+ XMMRegister z_reg = ToDoubleRegister(instr->z());
+ XMMRegister w_reg = ToDoubleRegister(instr->w());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ __ subq(rsp, Immediate(kFloat32x4Size));
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, x_reg);
+ __ movss(Operand(rsp, 0 * kFloatSize), xmm0);
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, y_reg);
+ __ movss(Operand(rsp, 1 * kFloatSize), xmm0);
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, z_reg);
+ __ movss(Operand(rsp, 2 * kFloatSize), xmm0);
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, w_reg);
+ __ movss(Operand(rsp, 3 * kFloatSize), xmm0);
+ __ movups(result_reg, Operand(rsp, 0 * kFloatSize));
+ __ addq(rsp, Immediate(kFloat32x4Size));
+ return;
+ }
+ case kInt32x4Constructor: {
+ ASSERT(instr->hydrogen()->x()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->y()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->z()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->w()->representation().IsInteger32());
+ Register x_reg = ToRegister(instr->x());
+ Register y_reg = ToRegister(instr->y());
+ Register z_reg = ToRegister(instr->z());
+ Register w_reg = ToRegister(instr->w());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ __ subq(rsp, Immediate(kInt32x4Size));
+ __ movl(Operand(rsp, 0 * kInt32Size), x_reg);
+ __ movl(Operand(rsp, 1 * kInt32Size), y_reg);
+ __ movl(Operand(rsp, 2 * kInt32Size), z_reg);
+ __ movl(Operand(rsp, 3 * kInt32Size), w_reg);
+ __ movups(result_reg, Operand(rsp, 0 * kInt32Size));
+ __ addq(rsp, Immediate(kInt32x4Size));
+ return;
+ }
+ case kInt32x4Bool: {
+ ASSERT(instr->hydrogen()->x()->representation().IsTagged());
+ ASSERT(instr->hydrogen()->y()->representation().IsTagged());
+ ASSERT(instr->hydrogen()->z()->representation().IsTagged());
+ ASSERT(instr->hydrogen()->w()->representation().IsTagged());
+ HType x_type = instr->hydrogen()->x()->type();
+ HType y_type = instr->hydrogen()->y()->type();
+ HType z_type = instr->hydrogen()->z()->type();
+ HType w_type = instr->hydrogen()->w()->type();
+ if (!x_type.IsBoolean() || !y_type.IsBoolean() ||
+ !z_type.IsBoolean() || !w_type.IsBoolean()) {
+ Comment(";;; deoptimize: other types for int32x4.bool.");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ Register x_reg = ToRegister(instr->x());
+ Register y_reg = ToRegister(instr->y());
+ Register z_reg = ToRegister(instr->z());
+ Register w_reg = ToRegister(instr->w());
+ Label load_false_x, done_x, load_false_y, done_y,
+ load_false_z, done_z, load_false_w, done_w;
+ __ subq(rsp, Immediate(kInt32x4Size));
+
+ __ CompareRoot(x_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_x, Label::kNear);
+ __ movl(Operand(rsp, 0 * kInt32Size), Immediate(-1));
+ __ jmp(&done_x, Label::kNear);
+ __ bind(&load_false_x);
+ __ movl(Operand(rsp, 0 * kInt32Size), Immediate(0x0));
+ __ bind(&done_x);
+
+ __ CompareRoot(y_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_y, Label::kNear);
+ __ movl(Operand(rsp, 1 * kInt32Size), Immediate(-1));
+ __ jmp(&done_y, Label::kNear);
+ __ bind(&load_false_y);
+ __ movl(Operand(rsp, 1 * kInt32Size), Immediate(0x0));
+ __ bind(&done_y);
+
+ __ CompareRoot(z_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_z, Label::kNear);
+ __ movl(Operand(rsp, 2 * kInt32Size), Immediate(-1));
+ __ jmp(&done_z, Label::kNear);
+ __ bind(&load_false_z);
+ __ movl(Operand(rsp, 2 * kInt32Size), Immediate(0x0));
+ __ bind(&done_z);
+
+ __ CompareRoot(w_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_w, Label::kNear);
+ __ movl(Operand(rsp, 3 * kInt32Size), Immediate(-1));
+ __ jmp(&done_w, Label::kNear);
+ __ bind(&load_false_w);
+ __ movl(Operand(rsp, 3 * kInt32Size), Immediate(0x0));
+ __ bind(&done_w);
+
+ __ movups(result_reg, Operand(rsp, 0));
+ __ addq(rsp, Immediate(kInt32x4Size));
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
void LCodeGen::DoPower(LPower* instr) {
Representation exponent_type = instr->hydrogen()->right()->representation();
// Having marked this as a call, we can use any registers.
ASSERT(ToRegister(instr->result()).is(rax));
int arity = instr->arity();
- CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
- if (instr->hydrogen()->IsTailCall()) {
- if (NeedsEagerFrame()) __ leave();
- __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
- } else {
- CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
- }
+ CallFunctionStub stub(arity, instr->hydrogen()->function_flags());
+ CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
}
DeoptimizeIf(cc, instr->environment());
}
}
- } else if (FLAG_track_double_fields && representation.IsDouble()) {
+ } else if (representation.IsDouble()) {
ASSERT(transition.is_null());
ASSERT(access.IsInobject());
ASSERT(!hinstr->NeedsWriteBarrier());
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
}
+
+ HandleExternalArrayOpRequiresPreScale(key, elements_kind);
}
int base_offset = instr->is_fixed_typed_array()
? FixedTypedArrayBase::kDataOffset - kHeapObjectTag
__ cvtsd2ss(value, value);
__ movss(operand, value);
} else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
- elements_kind == FLOAT64_ELEMENTS) {
+ elements_kind == FLOAT64_ELEMENTS) {
__ movsd(operand, ToDoubleRegister(instr->value()));
+ } else if (IsSIMD128ElementsKind(elements_kind)) {
+ __ movups(operand, ToSIMD128Register(instr->value()));
} else {
Register value(ToRegister(instr->value()));
switch (elements_kind) {
__ movl(operand, value);
break;
case EXTERNAL_FLOAT32_ELEMENTS:
+ case EXTERNAL_FLOAT32x4_ELEMENTS:
+ case EXTERNAL_INT32x4_ELEMENTS:
case EXTERNAL_FLOAT64_ELEMENTS:
case FLOAT32_ELEMENTS:
case FLOAT64_ELEMENTS:
+ case FLOAT32x4_ELEMENTS:
+ case INT32x4_ELEMENTS:
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
ASSERT(ToRegister(instr->left()).is(rdx));
ASSERT(ToRegister(instr->right()).is(rax));
StringAddStub stub(instr->hydrogen()->flags(),
- isolate()->heap()->GetPretenureMode());
+ instr->hydrogen()->pretenure_flag());
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
}
}
+void LCodeGen::DoDeferredSIMD128ToTagged(LSIMD128ToTagged* instr,
+ Runtime::FunctionId id) {
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ Register reg = ToRegister(instr->result());
+ __ Move(reg, Smi::FromInt(0));
+
+ {
+ PushSafepointRegistersScope scope(this);
+ __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+ __ CallRuntimeSaveDoubles(id);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+ __ movp(kScratchRegister, rax);
+ }
+ __ movp(reg, kScratchRegister);
+}
+
+
+template<class T>
+void LCodeGen::HandleSIMD128ToTagged(LSIMD128ToTagged* instr) {
+ class DeferredSIMD128ToTagged V8_FINAL : public LDeferredCode {
+ public:
+ DeferredSIMD128ToTagged(LCodeGen* codegen,
+ LSIMD128ToTagged* instr,
+ Runtime::FunctionId id)
+ : LDeferredCode(codegen), instr_(instr), id_(id) { }
+ virtual void Generate() V8_OVERRIDE {
+ codegen()->DoDeferredSIMD128ToTagged(instr_, id_);
+ }
+ virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
+ private:
+ LSIMD128ToTagged* instr_;
+ Runtime::FunctionId id_;
+ };
+
+ XMMRegister input_reg = ToSIMD128Register(instr->value());
+ Register reg = ToRegister(instr->result());
+ Register tmp = ToRegister(instr->temp());
+
+ DeferredSIMD128ToTagged* deferred =
+ new(zone()) DeferredSIMD128ToTagged(this, instr,
+ static_cast<Runtime::FunctionId>(T::kRuntimeAllocatorId()));
+ if (FLAG_inline_new) {
+ __ AllocateSIMDHeapObject(T::kSize, reg, tmp, deferred->entry(),
+ static_cast<Heap::RootListIndex>(T::kMapRootIndex()));
+ } else {
+ __ jmp(deferred->entry());
+ }
+ __ bind(deferred->exit());
+ __ movups(FieldOperand(reg, T::kValueOffset), input_reg);
+}
+
+
+void LCodeGen::DoSIMD128ToTagged(LSIMD128ToTagged* instr) {
+ if (instr->value()->IsFloat32x4Register()) {
+ HandleSIMD128ToTagged<Float32x4>(instr);
+ } else {
+ ASSERT(instr->value()->IsInt32x4Register());
+ HandleSIMD128ToTagged<Int32x4>(instr);
+ }
+}
+
+
void LCodeGen::DoSmiTag(LSmiTag* instr) {
ASSERT(instr->value()->Equals(instr->result()));
Register input = ToRegister(instr->value());
}
+template<class T>
+void LCodeGen::HandleTaggedToSIMD128(LTaggedToSIMD128* instr) {
+ LOperand* input = instr->value();
+ ASSERT(input->IsRegister());
+ LOperand* result = instr->result();
+ ASSERT(result->IsSIMD128Register());
+
+ Register input_reg = ToRegister(input);
+ XMMRegister result_reg = ToSIMD128Register(result);
+
+ Condition cc = masm()->CheckSmi(input_reg);
+ DeoptimizeIf(cc, instr->environment());
+ __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
+ static_cast<Heap::RootListIndex>(T::kMapRootIndex()));
+ DeoptimizeIf(not_equal, instr->environment());
+ __ movups(result_reg, FieldOperand(input_reg, T::kValueOffset));
+}
+
+
+void LCodeGen::DoTaggedToSIMD128(LTaggedToSIMD128* instr) {
+ if (instr->representation().IsFloat32x4()) {
+ HandleTaggedToSIMD128<Float32x4>(instr);
+ } else {
+ ASSERT(instr->representation().IsInt32x4());
+ HandleTaggedToSIMD128<Int32x4>(instr);
+ }
+}
+
+
void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
LOperand* input = instr->value();
ASSERT(input->IsDoubleRegister());
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
- __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
+ if (size <= Page::kMaxRegularHeapObjectSize) {
+ __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
+ } else {
+ __ jmp(deferred->entry());
+ }
} else {
Register size = ToRegister(instr->size());
__ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
final_branch_condition = equal;
+ } else if (type_name->Equals(heap()->float32x4_string())) {
+ __ JumpIfSmi(input, false_label, false_distance);
+ __ CmpObjectType(input, FLOAT32x4_TYPE, input);
+ final_branch_condition = equal;
+
+ } else if (type_name->Equals(heap()->int32x4_string())) {
+ __ JumpIfSmi(input, false_label, false_distance);
+ __ CmpObjectType(input, INT32x4_TYPE, input);
+ final_branch_condition = equal;
+
} else if (type_name->Equals(heap()->string_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);