Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Unified Diff: src/hydrogen.cc

Issue 148593004: A64: Synchronize with r18084. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 15089c0452fa9db913294bae5ed68c46b44c52cd..b92e80416f692e2c1208322e95872c4de15ba6e0 100644
--- a/src/hydrogen.cc
+++ b/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"
@@ -1197,7 +1198,7 @@ void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
HValue* reference = Add<HConstant>(ExternalReference(counter));
HValue* old_value = Add<HLoadNamedField>(reference,
HObjectAccess::ForCounter());
- HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1());
+ HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
new_value);
@@ -1275,17 +1276,14 @@ HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
}
-HValue* HGraphBuilder::BuildCheckString(
- HValue* object, const char* failure_reason) {
- if (!object->type().IsString()) {
- ASSERT(!object->IsConstant() ||
- !HConstant::cast(object)->HasStringValue());
- IfBuilder if_isstring(this);
- if_isstring.If<HIsStringAndBranch>(object);
- if_isstring.Then();
- if_isstring.ElseDeopt(failure_reason);
+HValue* HGraphBuilder::BuildCheckString(HValue* string) {
+ if (!string->type().IsString()) {
+ ASSERT(!string->IsConstant() ||
+ !HConstant::cast(string)->HasStringValue());
+ BuildCheckHeapObject(string);
+ return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
}
- return object;
+ return string;
}
@@ -1544,7 +1542,7 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
static_cast<HValue*>(NULL),
FAST_SMI_ELEMENTS);
- HValue* mask = Add<HSub>(capacity, graph()->GetConstant1());
+ HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
mask->ChangeRepresentation(Representation::Integer32());
mask->ClearFlag(HValue::kCanOverflow);
@@ -1576,8 +1574,8 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object,
// contains two elements (number and string) for each cache entry.
HValue* mask = AddLoadFixedArrayLength(number_string_cache);
mask->set_type(HType::Smi());
- mask = Add<HSar>(mask, graph()->GetConstant1());
- mask = Add<HSub>(mask, graph()->GetConstant1());
+ mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
+ mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
// Check whether object is a smi.
IfBuilder if_objectissmi(this);
@@ -1721,7 +1719,8 @@ void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
{
HValue* src_index = AddUncasted<HAdd>(src_offset, index);
- HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index);
+ HValue* value =
+ AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
}
@@ -1738,248 +1737,237 @@ HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left,
HValue* right_length = Add<HLoadNamedField>(
right, HObjectAccess::ForStringLength());
- // Check if we concatenated the strings here, or if we have to resort to the
- // runtime function.
- HIfContinuation handled(graph()->CreateBasicBlock(),
- graph()->CreateBasicBlock());
-
- // Check if both parameters do not exceed half the max string length, because
- // exceptionally long strings should be handled in the runtime. Unfortunately
- // we cannot actually check whether the combined length of both strings
- // exceeds String::kMaxLength (because of unclear results from the
- // representation inference phase), so we use a pessimistic approach here
- // instead, checking that the length of either substring does not exceed half
- // of String::kMaxLength.
- HConstant* max_length = Add<HConstant>(String::kMaxLength / 2);
- IfBuilder if_nooverflow(this);
- if_nooverflow.If<HCompareNumericAndBranch>(
- left_length, max_length, Token::LTE);
- if_nooverflow.AndIf<HCompareNumericAndBranch>(
- right_length, max_length, Token::LTE);
- if_nooverflow.Then();
+ // Compute the combined string length. If the result is larger than the max
+ // supported string length, we bailout to the runtime. This is done implicitly
+ // when converting the result back to a smi in case the max string length
+ // equals the max smi valie. Otherwise, for platforms with 32-bit smis, we do
+ HValue* length = AddUncasted<HAdd>(left_length, right_length);
+ STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
+ if (String::kMaxLength != Smi::kMaxValue) {
+ IfBuilder if_nooverflow(this);
+ if_nooverflow.If<HCompareNumericAndBranch>(
+ length, Add<HConstant>(String::kMaxLength), Token::LTE);
+ if_nooverflow.Then();
+ if_nooverflow.ElseDeopt("String length exceeds limit");
+ }
+
+ // Determine the string instance types.
+ HLoadNamedField* left_instance_type = Add<HLoadNamedField>(
+ Add<HLoadNamedField>(left, HObjectAccess::ForMap()),
+ HObjectAccess::ForMapInstanceType());
+ HLoadNamedField* right_instance_type = Add<HLoadNamedField>(
+ Add<HLoadNamedField>(right, HObjectAccess::ForMap()),
+ HObjectAccess::ForMapInstanceType());
+
+ // Compute difference of instance types.
+ HValue* xored_instance_types = AddUncasted<HBitwise>(
+ Token::BIT_XOR, left_instance_type, right_instance_type);
+
+ // Check if we should create a cons string.
+ IfBuilder if_createcons(this);
+ if_createcons.If<HCompareNumericAndBranch>(
+ length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
+ if_createcons.Then();
+ {
+ // Allocate the cons string object. HAllocate does not care whether we
+ // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
+ // CONS_STRING_TYPE here. Below we decide whether the cons string is
+ // one-byte or two-byte and set the appropriate map.
+ HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize),
+ HType::String(), pretenure_flag,
+ CONS_STRING_TYPE);
+
+ // Compute the intersection of instance types.
+ HValue* anded_instance_types = AddUncasted<HBitwise>(
+ Token::BIT_AND, left_instance_type, right_instance_type);
+
+ // We create a one-byte cons string if
+ // 1. both strings are one-byte, or
+ // 2. at least one of the strings is two-byte, but happens to contain only
+ // one-byte characters.
+ // To do this, we check
+ // 1. if both strings are one-byte, or if the one-byte data hint is set in
+ // both strings, or
+ // 2. if one of the strings has the one-byte data hint set and the other
+ // string is one-byte.
+ IfBuilder if_onebyte(this);
+ STATIC_ASSERT(kOneByteStringTag != 0);
+ STATIC_ASSERT(kOneByteDataHintMask != 0);
+ if_onebyte.If<HCompareNumericAndBranch>(
+ AddUncasted<HBitwise>(
+ Token::BIT_AND, anded_instance_types,
+ Add<HConstant>(static_cast<int32_t>(
+ kStringEncodingMask | kOneByteDataHintMask))),
+ graph()->GetConstant0(), Token::NE);
+ if_onebyte.Or();
+ STATIC_ASSERT(kOneByteStringTag != 0 &&
+ kOneByteDataHintTag != 0 &&
+ kOneByteDataHintTag != kOneByteStringTag);
+ if_onebyte.If<HCompareNumericAndBranch>(
+ AddUncasted<HBitwise>(
+ Token::BIT_AND, xored_instance_types,
+ Add<HConstant>(static_cast<int32_t>(
+ kOneByteStringTag | kOneByteDataHintTag))),
+ Add<HConstant>(static_cast<int32_t>(
+ kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
+ if_onebyte.Then();
+ {
+ // We can safely skip the write barrier for storing the map here.
+ Handle<Map> map = isolate()->factory()->cons_ascii_string_map();
+ AddStoreMapConstantNoWriteBarrier(string, map);
+ }
+ if_onebyte.Else();
+ {
+ // We can safely skip the write barrier for storing the map here.
+ Handle<Map> map = isolate()->factory()->cons_string_map();
+ AddStoreMapConstantNoWriteBarrier(string, map);
+ }
+ if_onebyte.End();
+
+ // Initialize the cons string fields.
+ Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
+ Add<HConstant>(String::kEmptyHashField));
+ Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length);
+ Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left);
+ Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(),
+ right);
+
+ // Count the native string addition.
+ AddIncrementCounter(isolate()->counters()->string_add_native());
+
+ // Cons string is result.
+ Push(string);
+ }
+ if_createcons.Else();
{
- // Determine the string instance types.
- HLoadNamedField* left_instance_type = Add<HLoadNamedField>(
- Add<HLoadNamedField>(left, HObjectAccess::ForMap()),
- HObjectAccess::ForMapInstanceType());
- HLoadNamedField* right_instance_type = Add<HLoadNamedField>(
- Add<HLoadNamedField>(right, HObjectAccess::ForMap()),
- HObjectAccess::ForMapInstanceType());
-
- // Compute difference of instance types.
- HValue* xored_instance_types = AddUncasted<HBitwise>(
- Token::BIT_XOR, left_instance_type, right_instance_type);
-
- // Compute the length of the resulting string.
- HValue* length = AddUncasted<HAdd>(left_length, right_length);
-
- // Check if we should create a cons string.
- IfBuilder if_createcons(this);
- if_createcons.If<HCompareNumericAndBranch>(
- length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
- if_createcons.Then();
+ // Compute union of instance types.
+ HValue* ored_instance_types = AddUncasted<HBitwise>(
+ Token::BIT_OR, left_instance_type, right_instance_type);
+
+ // Check if both strings have the same encoding and both are
+ // sequential.
+ IfBuilder if_sameencodingandsequential(this);
+ if_sameencodingandsequential.If<HCompareNumericAndBranch>(
+ AddUncasted<HBitwise>(
+ Token::BIT_AND, xored_instance_types,
+ Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
+ graph()->GetConstant0(), Token::EQ);
+ if_sameencodingandsequential.And();
+ STATIC_ASSERT(kSeqStringTag == 0);
+ if_sameencodingandsequential.If<HCompareNumericAndBranch>(
+ AddUncasted<HBitwise>(
+ Token::BIT_AND, ored_instance_types,
+ Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
+ graph()->GetConstant0(), Token::EQ);
+ if_sameencodingandsequential.Then();
{
- // Allocate the cons string object. HAllocate does not care whether we
- // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
- // CONS_STRING_TYPE here. Below we decide whether the cons string is
- // one-byte or two-byte and set the appropriate map.
- HAllocate* string = Add<HAllocate>(Add<HConstant>(ConsString::kSize),
- HType::String(), pretenure_flag,
- CONS_STRING_TYPE);
-
- // Compute the intersection of instance types.
- HValue* anded_instance_types = AddUncasted<HBitwise>(
- Token::BIT_AND, left_instance_type, right_instance_type);
-
- // We create a one-byte cons string if
- // 1. both strings are one-byte, or
- // 2. at least one of the strings is two-byte, but happens to contain only
- // one-byte characters.
- // To do this, we check
- // 1. if both strings are one-byte, or if the one-byte data hint is set in
- // both strings, or
- // 2. if one of the strings has the one-byte data hint set and the other
- // string is one-byte.
+ // Check if the result is a one-byte string.
IfBuilder if_onebyte(this);
STATIC_ASSERT(kOneByteStringTag != 0);
- STATIC_ASSERT(kOneByteDataHintMask != 0);
if_onebyte.If<HCompareNumericAndBranch>(
AddUncasted<HBitwise>(
- Token::BIT_AND, anded_instance_types,
- Add<HConstant>(static_cast<int32_t>(
- kStringEncodingMask | kOneByteDataHintMask))),
+ Token::BIT_AND, ored_instance_types,
+ Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
graph()->GetConstant0(), Token::NE);
- if_onebyte.Or();
- STATIC_ASSERT(kOneByteStringTag != 0 &&
- kOneByteDataHintTag != 0 &&
- kOneByteDataHintTag != kOneByteStringTag);
- if_onebyte.If<HCompareNumericAndBranch>(
- AddUncasted<HBitwise>(
- Token::BIT_AND, xored_instance_types,
- Add<HConstant>(static_cast<int32_t>(
- kOneByteStringTag | kOneByteDataHintTag))),
- Add<HConstant>(static_cast<int32_t>(
- kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
if_onebyte.Then();
{
- // We can safely skip the write barrier for storing the map here.
- Handle<Map> map = isolate()->factory()->cons_ascii_string_map();
+ // Calculate the number of bytes needed for the characters in the
+ // string while observing object alignment.
+ HValue* size = BuildSeqStringSizeFor(
+ length, String::ONE_BYTE_ENCODING);
+
+ // Allocate the ASCII string object.
+ Handle<Map> map = isolate()->factory()->ascii_string_map();
+ HAllocate* string = Add<HAllocate>(size, HType::String(),
+ pretenure_flag, ASCII_STRING_TYPE);
+ string->set_known_initial_map(map);
+
+ // We can safely skip the write barrier for storing map here.
AddStoreMapConstantNoWriteBarrier(string, map);
+
+ // Length must be stored into the string before we copy characters to
+ // make debug verification code happy.
+ Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
+ length);
+
+ // Copy bytes from the left string.
+ BuildCopySeqStringChars(
+ left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
+ string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
+ left_length);
+
+ // Copy bytes from the right string.
+ BuildCopySeqStringChars(
+ right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
+ string, left_length, String::ONE_BYTE_ENCODING,
+ right_length);
+
+ // Count the native string addition.
+ AddIncrementCounter(isolate()->counters()->string_add_native());
+
+ // Return the string.
+ Push(string);
}
if_onebyte.Else();
{
- // We can safely skip the write barrier for storing the map here.
- Handle<Map> map = isolate()->factory()->cons_string_map();
+ // Calculate the number of bytes needed for the characters in the
+ // string while observing object alignment.
+ HValue* size = BuildSeqStringSizeFor(
+ length, String::TWO_BYTE_ENCODING);
+
+ // Allocate the two-byte string object.
+ Handle<Map> map = isolate()->factory()->string_map();
+ HAllocate* string = Add<HAllocate>(size, HType::String(),
+ pretenure_flag, STRING_TYPE);
+ string->set_known_initial_map(map);
+
+ // We can safely skip the write barrier for storing map here.
AddStoreMapConstantNoWriteBarrier(string, map);
+
+ // Length must be stored into the string before we copy characters to
+ // make debug verification code happy.
+ Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
+ length);
+
+ // Copy bytes from the left string.
+ BuildCopySeqStringChars(
+ left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
+ string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
+ left_length);
+
+ // Copy bytes from the right string.
+ BuildCopySeqStringChars(
+ right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
+ string, left_length, String::TWO_BYTE_ENCODING,
+ right_length);
+
+ // Return the string.
+ Push(string);
}
if_onebyte.End();
- // Initialize the cons string fields.
+ // Initialize the (common) string fields.
+ HValue* string = Pop();
Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
Add<HConstant>(String::kEmptyHashField));
- Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(), length);
- Add<HStoreNamedField>(string, HObjectAccess::ForConsStringFirst(), left);
- Add<HStoreNamedField>(string, HObjectAccess::ForConsStringSecond(),
- right);
- // Cons string is result.
+ // Count the native string addition.
+ AddIncrementCounter(isolate()->counters()->string_add_native());
+
Push(string);
}
- if_createcons.Else();
+ if_sameencodingandsequential.Else();
{
- // Compute union of instance types.
- HValue* ored_instance_types = AddUncasted<HBitwise>(
- Token::BIT_OR, left_instance_type, right_instance_type);
-
- // Check if both strings have the same encoding and both are
- // sequential.
- IfBuilder if_sameencodingandsequential(this);
- if_sameencodingandsequential.If<HCompareNumericAndBranch>(
- AddUncasted<HBitwise>(
- Token::BIT_AND, xored_instance_types,
- Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
- graph()->GetConstant0(), Token::EQ);
- if_sameencodingandsequential.And();
- STATIC_ASSERT(kSeqStringTag == 0);
- if_sameencodingandsequential.If<HCompareNumericAndBranch>(
- AddUncasted<HBitwise>(
- Token::BIT_AND, ored_instance_types,
- Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
- graph()->GetConstant0(), Token::EQ);
- if_sameencodingandsequential.Then();
- {
- // Check if the result is a one-byte string.
- IfBuilder if_onebyte(this);
- STATIC_ASSERT(kOneByteStringTag != 0);
- if_onebyte.If<HCompareNumericAndBranch>(
- AddUncasted<HBitwise>(
- Token::BIT_AND, ored_instance_types,
- Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
- graph()->GetConstant0(), Token::NE);
- if_onebyte.Then();
- {
- // Calculate the number of bytes needed for the characters in the
- // string while observing object alignment.
- HValue* size = BuildSeqStringSizeFor(
- length, String::ONE_BYTE_ENCODING);
-
- // Allocate the ASCII string object.
- Handle<Map> map = isolate()->factory()->ascii_string_map();
- HAllocate* string = Add<HAllocate>(size, HType::String(),
- pretenure_flag, ASCII_STRING_TYPE);
- string->set_known_initial_map(map);
-
- // We can safely skip the write barrier for storing map here.
- AddStoreMapConstantNoWriteBarrier(string, map);
-
- // Length must be stored into the string before we copy characters to
- // make debug verification code happy.
- Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
- length);
-
- // Copy bytes from the left string.
- BuildCopySeqStringChars(
- left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
- string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
- left_length);
-
- // Copy bytes from the right string.
- BuildCopySeqStringChars(
- right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
- string, left_length, String::ONE_BYTE_ENCODING,
- right_length);
-
- // Return the string.
- Push(string);
- }
- if_onebyte.Else();
- {
- // Calculate the number of bytes needed for the characters in the
- // string while observing object alignment.
- HValue* size = BuildSeqStringSizeFor(
- length, String::TWO_BYTE_ENCODING);
-
- // Allocate the two-byte string object.
- Handle<Map> map = isolate()->factory()->string_map();
- HAllocate* string = Add<HAllocate>(size, HType::String(),
- pretenure_flag, STRING_TYPE);
- string->set_known_initial_map(map);
-
- // We can safely skip the write barrier for storing map here.
- AddStoreMapConstantNoWriteBarrier(string, map);
-
- // Length must be stored into the string before we copy characters to
- // make debug verification code happy.
- Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
- length);
-
- // Copy bytes from the left string.
- BuildCopySeqStringChars(
- left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
- string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
- left_length);
-
- // Copy bytes from the right string.
- BuildCopySeqStringChars(
- right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
- string, left_length, String::TWO_BYTE_ENCODING,
- right_length);
-
- // Return the string.
- Push(string);
- }
- if_onebyte.End();
-
- // Initialize the (common) string fields.
- HValue* string = Pop();
- Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
- Add<HConstant>(String::kEmptyHashField));
- Push(string);
- }
- if_sameencodingandsequential.JoinContinuation(&handled);
+ // Fallback to the runtime to add the two strings.
+ Add<HPushArgument>(left);
+ Add<HPushArgument>(right);
+ Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
+ Runtime::FunctionForId(Runtime::kStringAdd),
+ 2));
}
- if_createcons.JoinContinuation(&handled);
+ if_sameencodingandsequential.End();
}
- if_nooverflow.JoinContinuation(&handled);
-
- // Check if the strings were concatenated successfully, otherwise fallback to
- // add the strings in the runtime.
- IfBuilder if_handled(this, &handled);
- if_handled.Then();
- {
- // Count the native string addition.
- AddIncrementCounter(isolate()->counters()->string_add_native());
- }
- if_handled.Else();
- {
- // Fallback to the runtime to add the two strings.
- Add<HPushArgument>(left);
- Add<HPushArgument>(right);
- Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
- Runtime::FunctionForId(Runtime::kStringAdd),
- 2));
- }
- if_handled.End();
+ if_createcons.End();
return Pop();
}
@@ -5122,10 +5110,15 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
// pass an empty fixed array to the runtime function instead.
Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
int literal_index = expr->literal_index();
+ int flags = expr->depth() == 1
+ ? ArrayLiteral::kShallowElements
+ : ArrayLiteral::kNoFlags;
+ flags |= ArrayLiteral::kDisableMementos;
Add<HPushArgument>(Add<HConstant>(literals));
Add<HPushArgument>(Add<HConstant>(literal_index));
Add<HPushArgument>(Add<HConstant>(constants));
+ Add<HPushArgument>(Add<HConstant>(flags));
// TODO(mvstanton): Consider a flag to turn off creation of any
// AllocationMementos for this call: we are in crankshaft and should have
@@ -5133,7 +5126,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
Runtime::FunctionForId(function_id),
- 3);
+ 4);
// De-opt if elements kind changed from boilerplate_elements_kind.
Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
@@ -7508,16 +7501,6 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
return true;
}
break;
- case kMathRandom:
- if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
- AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
- Drop(1); // Receiver.
- HGlobalObject* global_object = Add<HGlobalObject>();
- HRandom* result = New<HRandom>(global_object);
- ast_context()->ReturnInstruction(result, expr->id());
- return true;
- }
- break;
case kMathMax:
case kMathMin:
if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
@@ -8097,6 +8080,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();
@@ -8115,31 +8134,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();
}
@@ -8158,6 +8273,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) == '_');
@@ -8641,8 +8766,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
Handle<Type> left_type,
Handle<Type> right_type,
Handle<Type> result_type,
- Maybe<int> fixed_right_arg,
- bool binop_stub) {
+ Maybe<int> fixed_right_arg) {
Representation left_rep = Representation::FromType(left_type);
Representation right_rep = Representation::FromType(right_type);
@@ -8676,14 +8800,12 @@ HValue* HGraphBuilder::BuildBinaryOperation(
(left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
// Validate type feedback for left argument.
if (left_type->Is(Type::String())) {
- left = BuildCheckString(
- left, "Expected string for LHS of binary operation");
+ left = BuildCheckString(left);
}
// Validate type feedback for right argument.
if (right_type->Is(Type::String())) {
- right = BuildCheckString(
- right, "Expected string for RHS of binary operation");
+ right = BuildCheckString(right);
}
// Convert left argument as necessary.
@@ -8713,7 +8835,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE);
}
- if (binop_stub) {
+ if (graph()->info()->IsStub()) {
left = EnforceNumberType(left, left_type);
right = EnforceNumberType(right, right_type);
}
@@ -8727,7 +8849,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
// Only the stub is allowed to call into the runtime, since otherwise we would
// inline several instructions (including the two pushes) for every tagged
// operation in optimized code, which is more expensive, than a stub call.
- if (binop_stub && is_non_primitive) {
+ if (graph()->info()->IsStub() && is_non_primitive) {
HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
Add<HPushArgument>(left);
Add<HPushArgument>(right);
@@ -8802,7 +8924,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
binop->set_observed_input_representation(1, left_rep);
binop->set_observed_input_representation(2, right_rep);
binop->initialize_output_representation(result_rep);
- if (binop_stub) {
+ if (graph()->info()->IsStub()) {
// Stub should not call into stub.
instr->SetFlag(HValue::kCannotBeTagged);
// And should truncate on HForceRepresentation already.
@@ -9220,7 +9342,7 @@ HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
Handle<JSObject> boilerplate_object,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
NoObservableSideEffectsScope no_effects(this);
InstanceType instance_type = boilerplate_object->map()->instance_type();
ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
@@ -9313,7 +9435,7 @@ void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader(
void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
Handle<JSObject> boilerplate_object,
HInstruction* object,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
Handle<DescriptorArray> descriptors(
boilerplate_object->map()->instance_descriptors());
int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
@@ -9385,7 +9507,7 @@ void HOptimizedGraphBuilder::BuildEmitElements(
Handle<JSObject> boilerplate_object,
Handle<FixedArrayBase> elements,
HValue* object_elements,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
ElementsKind kind = boilerplate_object->map()->elements_kind();
int elements_length = elements->length();
HValue* object_elements_length = Add<HConstant>(elements_length);
@@ -9426,7 +9548,7 @@ void HOptimizedGraphBuilder::BuildEmitFixedArray(
Handle<FixedArrayBase> elements,
ElementsKind kind,
HValue* object_elements,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
HInstruction* boilerplate_elements = Add<HConstant>(elements);
int elements_length = elements->length();
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
@@ -9892,14 +10014,6 @@ void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
}
-// Fast support for Math.random().
-void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
- HGlobalObject* global_object = Add<HGlobalObject>();
- HRandom* result = New<HRandom>(global_object);
- return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
// Fast support for StringAdd.
void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
ASSERT_EQ(2, call->arguments()->length());
@@ -9907,7 +10021,8 @@ void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
HValue* right = Pop();
HValue* left = Pop();
- HInstruction* result = New<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH);
+ HInstruction* result =
+ NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH);
return ast_context()->ReturnInstruction(result, call->id());
}
@@ -10036,7 +10151,7 @@ void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
ASSERT(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop();
- HInstruction* result = New<HUnaryMathOperation>(value, kMathSqrt);
+ HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
return ast_context()->ReturnInstruction(result, call->id());
}
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698