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

Unified Diff: src/hydrogen.cc

Issue 132373011: A64: Synchronize with r17635. (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 8bd2054c6fac12f241d9ed5b3b6aaca55578ddd4..2e5e1740117035a27f13030f97a7c4ab28783678 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -710,6 +710,21 @@ DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false)
#undef DEFINE_GET_CONSTANT
+#define DEFINE_IS_CONSTANT(Name, name) \
+bool HGraph::IsConstant##Name(HConstant* constant) { \
+ return constant_##name##_.is_set() && constant == constant_##name##_.get(); \
+}
+DEFINE_IS_CONSTANT(Undefined, undefined)
+DEFINE_IS_CONSTANT(0, 0)
+DEFINE_IS_CONSTANT(1, 1)
+DEFINE_IS_CONSTANT(Minus1, minus1)
+DEFINE_IS_CONSTANT(True, true)
+DEFINE_IS_CONSTANT(False, false)
+DEFINE_IS_CONSTANT(Hole, the_hole)
+DEFINE_IS_CONSTANT(Null, null)
+
+#undef DEFINE_IS_CONSTANT
+
HConstant* HGraph::GetInvalidContext() {
return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
@@ -717,14 +732,14 @@ HConstant* HGraph::GetInvalidContext() {
bool HGraph::IsStandardConstant(HConstant* constant) {
- if (constant == GetConstantUndefined()) return true;
- if (constant == GetConstant0()) return true;
- if (constant == GetConstant1()) return true;
- if (constant == GetConstantMinus1()) return true;
- if (constant == GetConstantTrue()) return true;
- if (constant == GetConstantFalse()) return true;
- if (constant == GetConstantHole()) return true;
- if (constant == GetConstantNull()) return true;
+ if (IsConstantUndefined(constant)) return true;
+ if (IsConstant0(constant)) return true;
+ if (IsConstant1(constant)) return true;
+ if (IsConstantMinus1(constant)) return true;
+ if (IsConstantTrue(constant)) return true;
+ if (IsConstantFalse(constant)) return true;
+ if (IsConstantHole(constant)) return true;
+ if (IsConstantNull(constant)) return true;
return false;
}
@@ -1456,6 +1471,342 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object,
}
+HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length,
+ String::Encoding encoding) {
+ STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
+ HValue* size = length;
+ if (encoding == String::TWO_BYTE_ENCODING) {
+ size = Add<HShl>(length, graph()->GetConstant1());
+ size->ClearFlag(HValue::kCanOverflow);
+ size->SetFlag(HValue::kUint32);
+ }
+ size = Add<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
+ SeqString::kHeaderSize + kObjectAlignmentMask)));
+ size->ClearFlag(HValue::kCanOverflow);
+ size = Add<HBitwise>(
+ Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
+ ~kObjectAlignmentMask)));
+ return size;
+}
+
+
+void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
+ HValue* src_offset,
+ String::Encoding src_encoding,
+ HValue* dst,
+ HValue* dst_offset,
+ String::Encoding dst_encoding,
+ HValue* length) {
+ ASSERT(dst_encoding != String::ONE_BYTE_ENCODING ||
+ src_encoding == String::ONE_BYTE_ENCODING);
+ LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
+ HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
+ {
+ HValue* src_index = Add<HAdd>(src_offset, index);
+ HValue* value = Add<HSeqStringGetChar>(src_encoding, src, src_index);
+ HValue* dst_index = Add<HAdd>(dst_offset, index);
+ Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
+ }
+ loop.EndBody();
+}
+
+
+HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left,
+ HValue* right,
+ PretenureFlag pretenure_flag) {
+ // Determine the string lengths.
+ HValue* left_length = Add<HLoadNamedField>(
+ left, HObjectAccess::ForStringLength());
+ 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();
+ {
+ // 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 = Add<HBitwise>(
+ Token::BIT_XOR, left_instance_type, right_instance_type);
+
+ // Compute the length of the resulting string.
+ HValue* length = Add<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();
+ {
+ // 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 = Add<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>(
+ Add<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>(
+ Add<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);
+
+ // Cons string is result.
+ Push(string);
+ }
+ if_createcons.Else();
+ {
+ // Compute union of instance types.
+ HValue* ored_instance_types = Add<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>(
+ Add<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>(
+ Add<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>(
+ Add<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);
+
+ // 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);
+
+ // 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));
+ Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
+ length);
+ Push(string);
+ }
+ if_sameencodingandsequential.JoinContinuation(&handled);
+ }
+ if_createcons.JoinContinuation(&handled);
+ }
+ 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();
+
+ return Pop();
+}
+
+
+HValue* HGraphBuilder::BuildStringAdd(HValue* left,
+ HValue* right,
+ PretenureFlag pretenure_flag) {
+ // Determine the string lengths.
+ HValue* left_length = Add<HLoadNamedField>(
+ left, HObjectAccess::ForStringLength());
+ HValue* right_length = Add<HLoadNamedField>(
+ right, HObjectAccess::ForStringLength());
+
+ // Check if left string is empty.
+ IfBuilder if_leftisempty(this);
+ if_leftisempty.If<HCompareNumericAndBranch>(
+ left_length, graph()->GetConstant0(), Token::EQ);
+ if_leftisempty.Then();
+ {
+ // Count the native string addition.
+ AddIncrementCounter(isolate()->counters()->string_add_native());
+
+ // Just return the right string.
+ Push(right);
+ }
+ if_leftisempty.Else();
+ {
+ // Check if right string is empty.
+ IfBuilder if_rightisempty(this);
+ if_rightisempty.If<HCompareNumericAndBranch>(
+ right_length, graph()->GetConstant0(), Token::EQ);
+ if_rightisempty.Then();
+ {
+ // Count the native string addition.
+ AddIncrementCounter(isolate()->counters()->string_add_native());
+
+ // Just return the left string.
+ Push(left);
+ }
+ if_rightisempty.Else();
+ {
+ // Concatenate the two non-empty strings.
+ Push(BuildUncheckedStringAdd(left, right, pretenure_flag));
+ }
+ if_rightisempty.End();
+ }
+ if_leftisempty.End();
+
+ return Pop();
+}
+
+
HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
HValue* checked_object,
HValue* key,
@@ -2283,7 +2634,8 @@ HGraph::HGraph(CompilationInfo* info)
depends_on_empty_array_proto_elements_(false),
type_change_checksum_(0),
maximum_environment_size_(0),
- no_side_effects_scope_count_(0) {
+ no_side_effects_scope_count_(0),
+ disallow_adding_new_values_(false) {
if (info->IsStub()) {
HydrogenCodeStub* stub = info->code_stub();
CodeStubInterfaceDescriptor* descriptor =
@@ -4312,6 +4664,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
+ expr->BuildConstantProperties(isolate());
Handle<JSFunction> closure = function_state()->compilation_info()->closure();
HInstruction* literal;
@@ -4433,6 +4786,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
+ expr->BuildConstantElements(isolate());
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
HInstruction* literal;
@@ -6393,18 +6747,6 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
return false;
}
-#if !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS
- // Target must be able to use caller's context.
- CompilationInfo* outer_info = current_info();
- if (target->context() != outer_info->closure()->context() ||
- outer_info->scope()->contains_with() ||
- outer_info->scope()->num_heap_slots() > 0) {
- TraceInline(target, caller, "target requires context change");
- return false;
- }
-#endif
-
-
// Don't inline deeper than the maximum number of inlining levels.
HEnvironment* env = environment();
int current_level = 1;
@@ -6542,15 +6884,9 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
undefined,
function_state()->inlining_kind(),
undefined_receiver);
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
- // IA32, ARM and MIPS only, overwrite the caller's context in the
- // deoptimization environment with the correct one.
- //
- // TODO(kmillikin): implement the same inlining on other platforms so we
- // can remove the unsightly ifdefs in this function.
+
HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
inner_env->BindContext(context);
-#endif
Add<HSimulate>(return_id);
current_block()->UpdateEnvironment(inner_env);
« 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