Generate TypedArrayInitialize builtin in hydrogen.
R=danno@chromium.org Review URL: https://codereview.chromium.org/59023003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18059 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5e177bd658
commit
c3a4d718ce
@ -1667,6 +1667,15 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
result = AssignEnvironment(result);
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
ASSERT(instr->left()->representation().IsExternal());
|
||||
ASSERT(instr->right()->representation().IsInteger32());
|
||||
ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
LOperand* right = UseOrConstantAtStart(instr->right());
|
||||
LAddI* add = new(zone()) LAddI(left, right);
|
||||
LInstruction* result = DefineAsRegister(add);
|
||||
return result;
|
||||
} else if (instr->representation().IsDouble()) {
|
||||
if (instr->left()->IsMul()) {
|
||||
return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
|
||||
|
@ -1262,6 +1262,26 @@ HValue* HBitwise::Canonicalize() {
|
||||
}
|
||||
|
||||
|
||||
Representation HAdd::RepresentationFromInputs() {
|
||||
Representation left_rep = left()->representation();
|
||||
if (left_rep.IsExternal()) {
|
||||
return Representation::External();
|
||||
}
|
||||
return HArithmeticBinaryOperation::RepresentationFromInputs();
|
||||
}
|
||||
|
||||
|
||||
Representation HAdd::RequiredInputRepresentation(int index) {
|
||||
if (index == 2) {
|
||||
Representation left_rep = left()->representation();
|
||||
if (left_rep.IsExternal()) {
|
||||
return Representation::Integer32();
|
||||
}
|
||||
}
|
||||
return HArithmeticBinaryOperation::RequiredInputRepresentation(index);
|
||||
}
|
||||
|
||||
|
||||
static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
|
||||
return arg1->representation().IsSpecialization() &&
|
||||
arg2->EqualsInteger32Constant(identity);
|
||||
|
@ -4732,8 +4732,9 @@ class HAdd V8_FINAL : public HArithmeticBinaryOperation {
|
||||
|
||||
// Add is only commutative if two integer values are added and not if two
|
||||
// tagged values are added (because it might be a String concatenation).
|
||||
// We also do not commute (pointer + offset).
|
||||
virtual bool IsCommutative() const V8_OVERRIDE {
|
||||
return !representation().IsTagged();
|
||||
return !representation().IsTagged() && !representation().IsExternal();
|
||||
}
|
||||
|
||||
virtual HValue* EnsureAndPropagateNotMinusZero(
|
||||
@ -4769,6 +4770,10 @@ class HAdd V8_FINAL : public HArithmeticBinaryOperation {
|
||||
}
|
||||
}
|
||||
|
||||
virtual Representation RepresentationFromInputs() V8_OVERRIDE;
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Add)
|
||||
|
||||
protected:
|
||||
@ -6062,6 +6067,43 @@ class HObjectAccess V8_FINAL {
|
||||
// Create an access for the payload of a Cell or JSGlobalPropertyCell.
|
||||
static HObjectAccess ForCellPayload(Isolate* isolate);
|
||||
|
||||
static HObjectAccess ForJSTypedArrayLength() {
|
||||
return HObjectAccess::ForJSObjectOffset(JSTypedArray::kLengthOffset);
|
||||
}
|
||||
|
||||
static HObjectAccess ForJSArrayBufferBackingStore() {
|
||||
return HObjectAccess::ForJSObjectOffset(
|
||||
JSArrayBuffer::kBackingStoreOffset, Representation::External());
|
||||
}
|
||||
|
||||
static HObjectAccess ForExternalArrayExternalPointer() {
|
||||
return HObjectAccess::ForJSObjectOffset(
|
||||
ExternalArray::kExternalPointerOffset, Representation::External());
|
||||
}
|
||||
|
||||
static HObjectAccess ForJSArrayBufferViewWeakNext() {
|
||||
return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kWeakNextOffset);
|
||||
}
|
||||
|
||||
static HObjectAccess ForJSArrayBufferWeakFirstView() {
|
||||
return HObjectAccess::ForJSObjectOffset(
|
||||
JSArrayBuffer::kWeakFirstViewOffset);
|
||||
}
|
||||
|
||||
static HObjectAccess ForJSArrayBufferViewBuffer() {
|
||||
return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kBufferOffset);
|
||||
}
|
||||
|
||||
static HObjectAccess ForJSArrayBufferViewByteOffset() {
|
||||
return HObjectAccess::ForJSObjectOffset(
|
||||
JSArrayBufferView::kByteOffsetOffset);
|
||||
}
|
||||
|
||||
static HObjectAccess ForJSArrayBufferViewByteLength() {
|
||||
return HObjectAccess::ForJSObjectOffset(
|
||||
JSArrayBufferView::kByteLengthOffset);
|
||||
}
|
||||
|
||||
void PrintTo(StringStream* stream);
|
||||
|
||||
inline bool Equals(HObjectAccess that) const {
|
||||
@ -6478,6 +6520,8 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
|
||||
} else if (field_representation().IsDouble() ||
|
||||
field_representation().IsSmi()) {
|
||||
return field_representation();
|
||||
} else if (field_representation().IsExternal()) {
|
||||
return Representation::External();
|
||||
}
|
||||
}
|
||||
return Representation::Tagged();
|
||||
|
187
src/hydrogen.cc
187
src/hydrogen.cc
@ -58,6 +58,7 @@
|
||||
#include "hydrogen-uint32-analysis.h"
|
||||
#include "lithium-allocator.h"
|
||||
#include "parser.h"
|
||||
#include "runtime.h"
|
||||
#include "scopeinfo.h"
|
||||
#include "scopes.h"
|
||||
#include "stub-cache.h"
|
||||
@ -8060,6 +8061,42 @@ const HOptimizedGraphBuilder::InlineFunctionGenerator
|
||||
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
|
||||
|
||||
|
||||
template <class ViewClass>
|
||||
void HGraphBuilder::BuildArrayBufferViewInitialization(
|
||||
HValue* obj,
|
||||
HValue* buffer,
|
||||
HValue* byte_offset,
|
||||
HValue* byte_length) {
|
||||
|
||||
for (int offset = ViewClass::kSize;
|
||||
offset < ViewClass::kSizeWithInternalFields;
|
||||
offset += kPointerSize) {
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(offset),
|
||||
Add<HConstant>(static_cast<int32_t>(0)));
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewByteOffset(),
|
||||
byte_offset);
|
||||
Add<HStoreNamedField>(
|
||||
obj,
|
||||
HObjectAccess::ForJSArrayBufferViewByteLength(),
|
||||
byte_length);
|
||||
|
||||
HObjectAccess weak_first_view_access =
|
||||
HObjectAccess::ForJSArrayBufferWeakFirstView();
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSArrayBufferViewWeakNext(),
|
||||
Add<HLoadNamedField>(buffer, weak_first_view_access));
|
||||
Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::VisitDataViewInitialize(
|
||||
CallRuntime* expr) {
|
||||
ZoneList<Expression*>* arguments = expr->arguments();
|
||||
@ -8078,31 +8115,127 @@ void HOptimizedGraphBuilder::VisitDataViewInitialize(
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(3)));
|
||||
HValue* byte_length = Pop();
|
||||
|
||||
for (int offset = JSDataView::kSize;
|
||||
offset < JSDataView::kSizeWithInternalFields;
|
||||
offset += kPointerSize) {
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(offset),
|
||||
Add<HConstant>(static_cast<int32_t>(0)));
|
||||
BuildArrayBufferViewInitialization<JSDataView>(
|
||||
obj, buffer, byte_offset, byte_length);
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
|
||||
CallRuntime* expr) {
|
||||
ZoneList<Expression*>* arguments = expr->arguments();
|
||||
|
||||
NoObservableSideEffectsScope scope(this);
|
||||
static const int kObjectArg = 0;
|
||||
static const int kArrayIdArg = 1;
|
||||
static const int kBufferArg = 2;
|
||||
static const int kByteOffsetArg = 3;
|
||||
static const int kByteLengthArg = 4;
|
||||
static const int kArgsLength = 5;
|
||||
ASSERT(arguments->length() == kArgsLength);
|
||||
|
||||
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
|
||||
HValue* obj = Pop();
|
||||
|
||||
ASSERT(arguments->at(kArrayIdArg)->node_type() == AstNode::kLiteral);
|
||||
Handle<Object> value =
|
||||
static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
|
||||
ASSERT(value->IsSmi());
|
||||
int array_id = Smi::cast(*value)->value();
|
||||
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
|
||||
HValue* buffer = Pop();
|
||||
|
||||
HValue* byte_offset;
|
||||
bool is_zero_byte_offset;
|
||||
|
||||
if (arguments->at(kByteOffsetArg)->node_type() == AstNode::kLiteral
|
||||
&& Smi::FromInt(0) ==
|
||||
*static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
|
||||
byte_offset = Add<HConstant>(static_cast<int32_t>(0));
|
||||
is_zero_byte_offset = true;
|
||||
} else {
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
|
||||
byte_offset = Pop();
|
||||
is_zero_byte_offset = false;
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer);
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset),
|
||||
byte_offset);
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset),
|
||||
byte_length);
|
||||
CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
|
||||
HValue* byte_length = Pop();
|
||||
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset),
|
||||
Add<HLoadNamedField>(buffer,
|
||||
HObjectAccess::ForJSObjectOffset(
|
||||
JSArrayBuffer::kWeakFirstViewOffset)));
|
||||
Add<HStoreNamedField>(buffer,
|
||||
HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset),
|
||||
obj);
|
||||
IfBuilder byte_offset_smi(this);
|
||||
|
||||
if (!is_zero_byte_offset) {
|
||||
byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
|
||||
byte_offset_smi.Then();
|
||||
}
|
||||
|
||||
{ // byte_offset is Smi.
|
||||
BuildArrayBufferViewInitialization<JSTypedArray>(
|
||||
obj, buffer, byte_offset, byte_length);
|
||||
|
||||
ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
|
||||
size_t element_size = 1; // Bogus initialization.
|
||||
Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size);
|
||||
|
||||
HInstruction* length = AddUncasted<HDiv>(byte_length,
|
||||
Add<HConstant>(static_cast<int32_t>(element_size)));
|
||||
|
||||
Add<HStoreNamedField>(obj,
|
||||
HObjectAccess::ForJSTypedArrayLength(),
|
||||
length);
|
||||
|
||||
HValue* elements =
|
||||
Add<HAllocate>(
|
||||
Add<HConstant>(ExternalArray::kAlignedSize),
|
||||
HType::JSArray(),
|
||||
NOT_TENURED,
|
||||
static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type));
|
||||
|
||||
Handle<Map> external_array_map(
|
||||
isolate()->heap()->MapForExternalArrayType(array_type));
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForMap(),
|
||||
Add<HConstant>(external_array_map));
|
||||
|
||||
HValue* backing_store = Add<HLoadNamedField>(
|
||||
buffer, HObjectAccess::ForJSArrayBufferBackingStore());
|
||||
|
||||
HValue* typed_array_start;
|
||||
if (is_zero_byte_offset) {
|
||||
typed_array_start = backing_store;
|
||||
} else {
|
||||
HInstruction* external_pointer =
|
||||
AddUncasted<HAdd>(backing_store, byte_offset);
|
||||
// Arguments are checked prior to call to TypedArrayInitialize,
|
||||
// including byte_offset.
|
||||
external_pointer->ClearFlag(HValue::kCanOverflow);
|
||||
typed_array_start = external_pointer;
|
||||
}
|
||||
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForExternalArrayExternalPointer(),
|
||||
typed_array_start);
|
||||
Add<HStoreNamedField>(elements,
|
||||
HObjectAccess::ForFixedArrayLength(),
|
||||
length);
|
||||
Add<HStoreNamedField>(
|
||||
obj, HObjectAccess::ForElementsPointer(), elements);
|
||||
}
|
||||
|
||||
if (!is_zero_byte_offset) {
|
||||
byte_offset_smi.Else();
|
||||
{ // byte_offset is not Smi.
|
||||
Push(Add<HPushArgument>(obj));
|
||||
VisitArgument(arguments->at(kArrayIdArg));
|
||||
Push(Add<HPushArgument>(buffer));
|
||||
Push(Add<HPushArgument>(byte_offset));
|
||||
Push(Add<HPushArgument>(byte_length));
|
||||
Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
|
||||
Drop(kArgsLength);
|
||||
}
|
||||
}
|
||||
byte_offset_smi.End();
|
||||
}
|
||||
|
||||
|
||||
@ -8121,6 +8254,16 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
|
||||
return VisitDataViewInitialize(expr);
|
||||
}
|
||||
|
||||
if (function->function_id == Runtime::kTypedArrayInitialize) {
|
||||
return VisitTypedArrayInitialize(expr);
|
||||
}
|
||||
|
||||
if (function->function_id == Runtime::kMaxSmi) {
|
||||
ASSERT(expr->arguments()->length() == 0);
|
||||
HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
|
||||
return ast_context()->ReturnInstruction(max_smi, expr->id());
|
||||
}
|
||||
|
||||
if (function->intrinsic_type == Runtime::INLINE) {
|
||||
ASSERT(expr->name()->length() > 0);
|
||||
ASSERT(expr->name()->Get(0) == '_');
|
||||
|
@ -1736,6 +1736,12 @@ class HGraphBuilder {
|
||||
position_ = position;
|
||||
}
|
||||
|
||||
template <typename ViewClass>
|
||||
void BuildArrayBufferViewInitialization(HValue* obj,
|
||||
HValue* buffer,
|
||||
HValue* byte_offset,
|
||||
HValue* byte_length);
|
||||
|
||||
private:
|
||||
HGraphBuilder();
|
||||
|
||||
@ -2195,6 +2201,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
|
||||
void VisitTypedArrayInitialize(CallRuntime* expr);
|
||||
|
||||
bool IsCallNewArrayInlineable(CallNew* expr);
|
||||
void BuildInlinedCallNewArray(CallNew* expr);
|
||||
|
||||
|
@ -1653,6 +1653,21 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
return result;
|
||||
} else if (instr->representation().IsDouble()) {
|
||||
return DoArithmeticD(Token::ADD, instr);
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
ASSERT(instr->left()->representation().IsExternal());
|
||||
ASSERT(instr->right()->representation().IsInteger32());
|
||||
ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
bool use_lea = LAddI::UseLea(instr);
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
HValue* right_candidate = instr->right();
|
||||
LOperand* right = use_lea
|
||||
? UseRegisterOrConstantAtStart(right_candidate)
|
||||
: UseOrConstantAtStart(right_candidate);
|
||||
LAddI* add = new(zone()) LAddI(left, right);
|
||||
LInstruction* result = use_lea
|
||||
? DefineAsRegister(add)
|
||||
: DefineSameAsFirst(add);
|
||||
return result;
|
||||
} else {
|
||||
return DoArithmeticT(Token::ADD, instr);
|
||||
}
|
||||
|
@ -131,6 +131,10 @@ class Representation {
|
||||
}
|
||||
|
||||
bool is_more_general_than(const Representation& other) const {
|
||||
if (kind_ == kExternal && other.kind_ == kNone) return true;
|
||||
if (kind_ == kExternal && other.kind_ == kExternal) return false;
|
||||
if (kind_ == kNone && other.kind_ == kExternal) return false;
|
||||
|
||||
ASSERT(kind_ != kExternal);
|
||||
ASSERT(other.kind_ != kExternal);
|
||||
if (IsHeapObject()) return other.IsDouble() || other.IsNone();
|
||||
|
@ -863,20 +863,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
|
||||
}
|
||||
|
||||
|
||||
enum TypedArrayId {
|
||||
// arrayIds below should be synchromized with typedarray.js natives.
|
||||
ARRAY_ID_UINT8 = 1,
|
||||
ARRAY_ID_INT8 = 2,
|
||||
ARRAY_ID_UINT16 = 3,
|
||||
ARRAY_ID_INT16 = 4,
|
||||
ARRAY_ID_UINT32 = 5,
|
||||
ARRAY_ID_INT32 = 6,
|
||||
ARRAY_ID_FLOAT32 = 7,
|
||||
ARRAY_ID_FLOAT64 = 8,
|
||||
ARRAY_ID_UINT8C = 9
|
||||
};
|
||||
|
||||
static void ArrayIdToTypeAndSize(
|
||||
void Runtime::ArrayIdToTypeAndSize(
|
||||
int arrayId, ExternalArrayType* array_type, size_t* element_size) {
|
||||
switch (arrayId) {
|
||||
case ARRAY_ID_UINT8:
|
||||
@ -938,7 +925,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
|
||||
|
||||
ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
|
||||
size_t element_size = 1; // Bogus initialization.
|
||||
ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
|
||||
Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
|
||||
|
||||
holder->set_buffer(*buffer);
|
||||
holder->set_byte_offset(*byte_offset_object);
|
||||
@ -990,7 +977,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
|
||||
|
||||
ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
|
||||
size_t element_size = 1; // Bogus initialization.
|
||||
ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
|
||||
Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
|
||||
|
||||
Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
|
||||
size_t length = NumberToSize(isolate, *length_obj);
|
||||
|
@ -830,6 +830,22 @@ class Runtime : public AllStatic {
|
||||
Isolate* isolate,
|
||||
JSArrayBuffer* phantom_array_buffer);
|
||||
|
||||
enum TypedArrayId {
|
||||
// arrayIds below should be synchromized with typedarray.js natives.
|
||||
ARRAY_ID_UINT8 = 1,
|
||||
ARRAY_ID_INT8 = 2,
|
||||
ARRAY_ID_UINT16 = 3,
|
||||
ARRAY_ID_INT16 = 4,
|
||||
ARRAY_ID_UINT32 = 5,
|
||||
ARRAY_ID_INT32 = 6,
|
||||
ARRAY_ID_FLOAT32 = 7,
|
||||
ARRAY_ID_FLOAT64 = 8,
|
||||
ARRAY_ID_UINT8C = 9
|
||||
};
|
||||
|
||||
static void ArrayIdToTypeAndSize(int array_id,
|
||||
ExternalArrayType *type, size_t *element_size);
|
||||
|
||||
// Helper functions used stubs.
|
||||
static void PerformGC(Object* result, Isolate* isolate);
|
||||
|
||||
|
@ -78,7 +78,8 @@ macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
|
||||
var newLength = ToPositiveInteger(length, "invalid_typed_array_length");
|
||||
newByteLength = newLength * ELEMENT_SIZE;
|
||||
}
|
||||
if (offset + newByteLength > bufferByteLength) {
|
||||
if ((offset + newByteLength > bufferByteLength)
|
||||
|| (newLength > %MaxSmi())) {
|
||||
throw MakeRangeError("invalid_typed_array_length");
|
||||
}
|
||||
%TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength);
|
||||
|
@ -1781,14 +1781,22 @@ void LCodeGen::DoAddI(LAddI* instr) {
|
||||
LOperand* left = instr->left();
|
||||
LOperand* right = instr->right();
|
||||
|
||||
Representation target_rep = instr->hydrogen()->representation();
|
||||
bool is_q = target_rep.IsSmi() || target_rep.IsExternal();
|
||||
|
||||
if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
|
||||
if (right->IsConstantOperand()) {
|
||||
int32_t offset = ToInteger32(LConstantOperand::cast(right));
|
||||
__ leal(ToRegister(instr->result()),
|
||||
MemOperand(ToRegister(left), offset));
|
||||
if (is_q) {
|
||||
__ lea(ToRegister(instr->result()),
|
||||
MemOperand(ToRegister(left), offset));
|
||||
} else {
|
||||
__ leal(ToRegister(instr->result()),
|
||||
MemOperand(ToRegister(left), offset));
|
||||
}
|
||||
} else {
|
||||
Operand address(ToRegister(left), ToRegister(right), times_1, 0);
|
||||
if (instr->hydrogen()->representation().IsSmi()) {
|
||||
if (is_q) {
|
||||
__ lea(ToRegister(instr->result()), address);
|
||||
} else {
|
||||
__ leal(ToRegister(instr->result()), address);
|
||||
@ -1796,16 +1804,21 @@ void LCodeGen::DoAddI(LAddI* instr) {
|
||||
}
|
||||
} else {
|
||||
if (right->IsConstantOperand()) {
|
||||
__ addl(ToRegister(left),
|
||||
Immediate(ToInteger32(LConstantOperand::cast(right))));
|
||||
if (is_q) {
|
||||
__ addq(ToRegister(left),
|
||||
Immediate(ToInteger32(LConstantOperand::cast(right))));
|
||||
} else {
|
||||
__ addl(ToRegister(left),
|
||||
Immediate(ToInteger32(LConstantOperand::cast(right))));
|
||||
}
|
||||
} else if (right->IsRegister()) {
|
||||
if (instr->hydrogen_value()->representation().IsSmi()) {
|
||||
if (is_q) {
|
||||
__ addq(ToRegister(left), ToRegister(right));
|
||||
} else {
|
||||
__ addl(ToRegister(left), ToRegister(right));
|
||||
}
|
||||
} else {
|
||||
if (instr->hydrogen_value()->representation().IsSmi()) {
|
||||
if (is_q) {
|
||||
__ addq(ToRegister(left), ToOperand(right));
|
||||
} else {
|
||||
__ addl(ToRegister(left), ToOperand(right));
|
||||
|
@ -1557,6 +1557,21 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
result = AssignEnvironment(result);
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
ASSERT(instr->left()->representation().IsExternal());
|
||||
ASSERT(instr->right()->representation().IsInteger32());
|
||||
ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
bool use_lea = LAddI::UseLea(instr);
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
HValue* right_candidate = instr->right();
|
||||
LOperand* right = use_lea
|
||||
? UseRegisterOrConstantAtStart(right_candidate)
|
||||
: UseOrConstantAtStart(right_candidate);
|
||||
LAddI* add = new(zone()) LAddI(left, right);
|
||||
LInstruction* result = use_lea
|
||||
? DefineAsRegister(add)
|
||||
: DefineSameAsFirst(add);
|
||||
return result;
|
||||
} else if (instr->representation().IsDouble()) {
|
||||
return DoArithmeticD(Token::ADD, instr);
|
||||
} else {
|
||||
|
@ -121,4 +121,8 @@ TEST(RepresentationMoreGeneralThan) {
|
||||
TestPairNegative(Representation::HeapObject(), Representation::Integer32());
|
||||
TestPairPositive(Representation::Double(), Representation::Integer32());
|
||||
TestPairPositive(Representation::Tagged(), Representation::Integer32());
|
||||
|
||||
TestPairNegative(Representation::None(), Representation::External());
|
||||
TestPairNegative(Representation::External(), Representation::External());
|
||||
TestPairPositive(Representation::External(), Representation::None());
|
||||
}
|
||||
|
@ -204,6 +204,9 @@ var knownProblems = {
|
||||
"_OneByteSeqStringSetChar": true,
|
||||
"_TwoByteSeqStringSetChar": true,
|
||||
|
||||
// Only applicable to TypedArrays.
|
||||
"TypedArrayInitialize": true,
|
||||
|
||||
// Only applicable to generators.
|
||||
"_GeneratorNext": true,
|
||||
"_GeneratorThrow": true,
|
||||
|
@ -205,6 +205,9 @@ var knownProblems = {
|
||||
"_OneByteSeqStringSetChar": true,
|
||||
"_TwoByteSeqStringSetChar": true,
|
||||
|
||||
// Only applicable to TypedArrays.
|
||||
"TypedArrayInitialize": true,
|
||||
|
||||
// Only applicable to generators.
|
||||
"_GeneratorNext": true,
|
||||
"_GeneratorThrow": true,
|
||||
|
@ -204,6 +204,9 @@ var knownProblems = {
|
||||
"_OneByteSeqStringSetChar": true,
|
||||
"_TwoByteSeqStringSetChar": true,
|
||||
|
||||
// Only applicable to TypedArrays.
|
||||
"TypedArrayInitialize": true,
|
||||
|
||||
// Only applicable to generators.
|
||||
"_GeneratorNext": true,
|
||||
"_GeneratorThrow": true,
|
||||
|
@ -204,6 +204,9 @@ var knownProblems = {
|
||||
"_OneByteSeqStringSetChar": true,
|
||||
"_TwoByteSeqStringSetChar": true,
|
||||
|
||||
// Only applicable to TypedArrays.
|
||||
"TypedArrayInitialize": true,
|
||||
|
||||
// Only applicable to generators.
|
||||
"_GeneratorNext": true,
|
||||
"_GeneratorThrow": true,
|
||||
|
Loading…
Reference in New Issue
Block a user