| Index: src/hydrogen.cc
 | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
 | 
| index 7bdc02f79c7da451c614949dac604c742906c1fc..3fcce8046d354b469411f19d8927e3a97dfd578d 100644
 | 
| --- a/src/hydrogen.cc
 | 
| +++ b/src/hydrogen.cc
 | 
| @@ -1693,131 +1693,22 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HAllocate* HGraphBuilder::BuildAllocate(
 | 
| -    HValue* object_size,
 | 
| -    HType type,
 | 
| -    InstanceType instance_type,
 | 
| -    HAllocationMode allocation_mode) {
 | 
| -  // Compute the effective allocation size.
 | 
| -  HValue* size = object_size;
 | 
| -  if (allocation_mode.CreateAllocationMementos()) {
 | 
| -    size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
 | 
| +HValue* HGraphBuilder::BuildSeqStringSizeFor(HValue* length,
 | 
| +                                             String::Encoding encoding) {
 | 
| +  STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
 | 
| +  HValue* size = length;
 | 
| +  if (encoding == String::TWO_BYTE_ENCODING) {
 | 
| +    size = AddUncasted<HShl>(length, graph()->GetConstant1());
 | 
|      size->ClearFlag(HValue::kCanOverflow);
 | 
| +    size->SetFlag(HValue::kUint32);
 | 
|    }
 | 
| -
 | 
| -  // Perform the actual allocation.
 | 
| -  HAllocate* object = Add<HAllocate>(
 | 
| -      size, type, allocation_mode.GetPretenureMode(),
 | 
| -      instance_type, allocation_mode.feedback_site());
 | 
| -
 | 
| -  // Setup the allocation memento.
 | 
| -  if (allocation_mode.CreateAllocationMementos()) {
 | 
| -    BuildCreateAllocationMemento(
 | 
| -        object, object_size, allocation_mode.current_site());
 | 
| -  }
 | 
| -
 | 
| -  return object;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
 | 
| -                                             HValue* right_length) {
 | 
| -  // 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 value. 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");
 | 
| -  }
 | 
| -  return length;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -HValue* HGraphBuilder::BuildCreateConsString(
 | 
| -    HValue* length,
 | 
| -    HValue* left,
 | 
| -    HValue* right,
 | 
| -    HAllocationMode allocation_mode) {
 | 
| -  // Determine the string instance types.
 | 
| -  HInstruction* left_instance_type = AddLoadStringInstanceType(left);
 | 
| -  HInstruction* right_instance_type = AddLoadStringInstanceType(right);
 | 
| -
 | 
| -  // 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.
 | 
| -  ASSERT(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
 | 
| -                                            CONS_ASCII_STRING_TYPE));
 | 
| -  HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
 | 
| -                                    HType::String(), CONS_STRING_TYPE,
 | 
| -                                    allocation_mode);
 | 
| -
 | 
| -  // Compute intersection and difference of instance types.
 | 
| -  HValue* anded_instance_types = AddUncasted<HBitwise>(
 | 
| -      Token::BIT_AND, left_instance_type, right_instance_type);
 | 
| -  HValue* xored_instance_types = AddUncasted<HBitwise>(
 | 
| -      Token::BIT_XOR, 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(result, 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(result, map);
 | 
| -  }
 | 
| -  if_onebyte.End();
 | 
| -
 | 
| -  // Initialize the cons string fields.
 | 
| -  Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
 | 
| -                        Add<HConstant>(String::kEmptyHashField));
 | 
| -  Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
 | 
| -  Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
 | 
| -  Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
 | 
| -
 | 
| -  // Count the native string addition.
 | 
| -  AddIncrementCounter(isolate()->counters()->string_add_native());
 | 
| -
 | 
| -  return result;
 | 
| +  size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
 | 
| +              SeqString::kHeaderSize + kObjectAlignmentMask)));
 | 
| +  size->ClearFlag(HValue::kCanOverflow);
 | 
| +  size = AddUncasted<HBitwise>(
 | 
| +      Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
 | 
| +              ~kObjectAlignmentMask)));
 | 
| +  return size;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1843,54 +1734,123 @@ void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HValue* HGraphBuilder::BuildUncheckedStringAdd(
 | 
| -    HValue* left,
 | 
| -    HValue* right,
 | 
| -    HAllocationMode allocation_mode) {
 | 
| +HValue* HGraphBuilder::BuildUncheckedStringAdd(HValue* left,
 | 
| +                                               HValue* right,
 | 
| +                                               PretenureFlag pretenure_flag) {
 | 
|    // Determine the string lengths.
 | 
| -  HValue* left_length = AddLoadStringLength(left);
 | 
| -  HValue* right_length = AddLoadStringLength(right);
 | 
| +  HValue* left_length = Add<HLoadNamedField>(
 | 
| +      left, HObjectAccess::ForStringLength());
 | 
| +  HValue* right_length = Add<HLoadNamedField>(
 | 
| +      right, HObjectAccess::ForStringLength());
 | 
|  
 | 
| -  // Compute the combined string length.
 | 
| -  HValue* length = BuildAddStringLengths(left_length, right_length);
 | 
| -
 | 
| -  // Do some manual constant folding here.
 | 
| -  if (left_length->IsConstant()) {
 | 
| -    HConstant* c_left_length = HConstant::cast(left_length);
 | 
| -    ASSERT_NE(0, c_left_length->Integer32Value());
 | 
| -    if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
 | 
| -      // The right string contains at least one character.
 | 
| -      return BuildCreateConsString(length, left, right, allocation_mode);
 | 
| -    }
 | 
| -  } else if (right_length->IsConstant()) {
 | 
| -    HConstant* c_right_length = HConstant::cast(right_length);
 | 
| -    ASSERT_NE(0, c_right_length->Integer32Value());
 | 
| -    if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
 | 
| -      // The left string contains at least one character.
 | 
| -      return BuildCreateConsString(length, left, right, allocation_mode);
 | 
| -    }
 | 
| +  // 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();
 | 
|    {
 | 
| -    // Create a cons string.
 | 
| -    Push(BuildCreateConsString(length, left, right, allocation_mode));
 | 
| +    // 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.
 | 
| +    ASSERT(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
 | 
| +                                              CONS_ASCII_STRING_TYPE));
 | 
| +    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.
 | 
| -    HValue* left_instance_type = AddLoadStringInstanceType(left);
 | 
| -    HValue* right_instance_type = AddLoadStringInstanceType(right);
 | 
| -
 | 
| -    // Compute union and difference of instance types.
 | 
| +    // Compute union of instance types.
 | 
|      HValue* ored_instance_types = AddUncasted<HBitwise>(
 | 
|          Token::BIT_OR, left_instance_type, right_instance_type);
 | 
| -    HValue* xored_instance_types = AddUncasted<HBitwise>(
 | 
| -        Token::BIT_XOR, left_instance_type, right_instance_type);
 | 
|  
 | 
|      // Check if both strings have the same encoding and both are
 | 
|      // sequential.
 | 
| @@ -1909,12 +1869,7 @@ HValue* HGraphBuilder::BuildUncheckedStringAdd(
 | 
|          graph()->GetConstant0(), Token::EQ);
 | 
|      if_sameencodingandsequential.Then();
 | 
|      {
 | 
| -      HConstant* string_map =
 | 
| -          Add<HConstant>(isolate()->factory()->string_map());
 | 
| -      HConstant* ascii_string_map =
 | 
| -          Add<HConstant>(isolate()->factory()->ascii_string_map());
 | 
| -
 | 
| -      // Determine map and size depending on whether result is one-byte string.
 | 
| +      // Check if the result is a one-byte string.
 | 
|        IfBuilder if_onebyte(this);
 | 
|        STATIC_ASSERT(kOneByteStringTag != 0);
 | 
|        if_onebyte.If<HCompareNumericAndBranch>(
 | 
| @@ -1924,84 +1879,90 @@ HValue* HGraphBuilder::BuildUncheckedStringAdd(
 | 
|            graph()->GetConstant0(), Token::NE);
 | 
|        if_onebyte.Then();
 | 
|        {
 | 
| -        // Allocate sequential one-byte string object.
 | 
| -        Push(length);
 | 
| -        Push(ascii_string_map);
 | 
| -      }
 | 
| -      if_onebyte.Else();
 | 
| -      {
 | 
| -        // Allocate sequential two-byte string object.
 | 
| -        HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
 | 
| -        size->ClearFlag(HValue::kCanOverflow);
 | 
| -        size->SetFlag(HValue::kUint32);
 | 
| -        Push(size);
 | 
| -        Push(string_map);
 | 
| -      }
 | 
| -      if_onebyte.End();
 | 
| -      HValue* map = Pop();
 | 
| -
 | 
| -      // Calculate the number of bytes needed for the characters in the
 | 
| -      // string while observing object alignment.
 | 
| -      STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
 | 
| -      HValue* size = Pop();
 | 
| -      size = AddUncasted<HAdd>(size, Add<HConstant>(static_cast<int32_t>(
 | 
| -                  SeqString::kHeaderSize + kObjectAlignmentMask)));
 | 
| -      size->ClearFlag(HValue::kCanOverflow);
 | 
| -      size = AddUncasted<HBitwise>(
 | 
| -          Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
 | 
| -                  ~kObjectAlignmentMask)));
 | 
| -
 | 
| -      // Allocate the string object. HAllocate does not care whether we pass
 | 
| -      // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here.
 | 
| -      HAllocate* result = BuildAllocate(
 | 
| -          size, HType::String(), STRING_TYPE, allocation_mode);
 | 
| -
 | 
| -      // We can safely skip the write barrier for storing map here.
 | 
| -      AddStoreMapNoWriteBarrier(result, map);
 | 
| -
 | 
| -      // Initialize the string fields.
 | 
| -      Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
 | 
| -                            Add<HConstant>(String::kEmptyHashField));
 | 
| -      Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
 | 
| -
 | 
| -      // Copy characters to the result string.
 | 
| -      IfBuilder if_twobyte(this);
 | 
| -      if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
 | 
| -      if_twobyte.Then();
 | 
| -      {
 | 
| -        // Copy characters from the left string.
 | 
| +        // 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::TWO_BYTE_ENCODING,
 | 
| -            result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
 | 
| +            left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
 | 
| +            string, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
 | 
|              left_length);
 | 
|  
 | 
| -        // Copy characters from the right string.
 | 
| +        // Copy bytes from the right string.
 | 
|          BuildCopySeqStringChars(
 | 
| -            right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
 | 
| -            result, left_length, String::TWO_BYTE_ENCODING,
 | 
| +            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_twobyte.Else();
 | 
| +      if_onebyte.Else();
 | 
|        {
 | 
| -        // Copy characters from the left string.
 | 
| +        // 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::ONE_BYTE_ENCODING,
 | 
| -            result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
 | 
| +            left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
 | 
| +            string, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
 | 
|              left_length);
 | 
|  
 | 
| -        // Copy characters from the right string.
 | 
| +        // Copy bytes from the right string.
 | 
|          BuildCopySeqStringChars(
 | 
| -            right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
 | 
| -            result, left_length, String::ONE_BYTE_ENCODING,
 | 
| +            right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
 | 
| +            string, left_length, String::TWO_BYTE_ENCODING,
 | 
|              right_length);
 | 
| +
 | 
| +        // Return the string.
 | 
| +        Push(string);
 | 
|        }
 | 
| -      if_twobyte.End();
 | 
| +      if_onebyte.End();
 | 
| +
 | 
| +      // Initialize the (common) string fields.
 | 
| +      HValue* string = Pop();
 | 
| +      Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
 | 
| +                            Add<HConstant>(String::kEmptyHashField));
 | 
|  
 | 
|        // Count the native string addition.
 | 
|        AddIncrementCounter(isolate()->counters()->string_add_native());
 | 
|  
 | 
| -      // Return the sequential string.
 | 
| -      Push(result);
 | 
| +      Push(string);
 | 
|      }
 | 
|      if_sameencodingandsequential.Else();
 | 
|      {
 | 
| @@ -2020,21 +1981,20 @@ HValue* HGraphBuilder::BuildUncheckedStringAdd(
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HValue* HGraphBuilder::BuildStringAdd(
 | 
| -    HValue* left,
 | 
| -    HValue* right,
 | 
| -    HAllocationMode allocation_mode) {
 | 
| -  NoObservableSideEffectsScope no_effects(this);
 | 
| -
 | 
| -  // Determine string lengths.
 | 
| -  HValue* left_length = AddLoadStringLength(left);
 | 
| -  HValue* right_length = AddLoadStringLength(right);
 | 
| +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_leftempty(this);
 | 
| -  if_leftempty.If<HCompareNumericAndBranch>(
 | 
| +  IfBuilder if_leftisempty(this);
 | 
| +  if_leftisempty.If<HCompareNumericAndBranch>(
 | 
|        left_length, graph()->GetConstant0(), Token::EQ);
 | 
| -  if_leftempty.Then();
 | 
| +  if_leftisempty.Then();
 | 
|    {
 | 
|      // Count the native string addition.
 | 
|      AddIncrementCounter(isolate()->counters()->string_add_native());
 | 
| @@ -2042,13 +2002,13 @@ HValue* HGraphBuilder::BuildStringAdd(
 | 
|      // Just return the right string.
 | 
|      Push(right);
 | 
|    }
 | 
| -  if_leftempty.Else();
 | 
| +  if_leftisempty.Else();
 | 
|    {
 | 
|      // Check if right string is empty.
 | 
| -    IfBuilder if_rightempty(this);
 | 
| -    if_rightempty.If<HCompareNumericAndBranch>(
 | 
| +    IfBuilder if_rightisempty(this);
 | 
| +    if_rightisempty.If<HCompareNumericAndBranch>(
 | 
|          right_length, graph()->GetConstant0(), Token::EQ);
 | 
| -    if_rightempty.Then();
 | 
| +    if_rightisempty.Then();
 | 
|      {
 | 
|        // Count the native string addition.
 | 
|        AddIncrementCounter(isolate()->counters()->string_add_native());
 | 
| @@ -2056,14 +2016,14 @@ HValue* HGraphBuilder::BuildStringAdd(
 | 
|        // Just return the left string.
 | 
|        Push(left);
 | 
|      }
 | 
| -    if_rightempty.Else();
 | 
| +    if_rightisempty.Else();
 | 
|      {
 | 
| -      // Add the two non-empty strings.
 | 
| -      Push(BuildUncheckedStringAdd(left, right, allocation_mode));
 | 
| +      // Concatenate the two non-empty strings.
 | 
| +      Push(BuildUncheckedStringAdd(left, right, pretenure_flag));
 | 
|      }
 | 
| -    if_rightempty.End();
 | 
| +    if_rightisempty.End();
 | 
|    }
 | 
| -  if_leftempty.End();
 | 
| +  if_leftisempty.End();
 | 
|  
 | 
|    return Pop();
 | 
|  }
 | 
| @@ -6140,27 +6100,15 @@ HInstruction* HGraphBuilder::AddLoadNamedField(HValue* object,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
 | 
| -  if (string->IsConstant()) {
 | 
| -    HConstant* c_string = HConstant::cast(string);
 | 
| -    if (c_string->HasStringValue()) {
 | 
| -      return Add<HConstant>(c_string->StringValue()->map()->instance_type());
 | 
| +HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object,
 | 
| +                                                   HValue* checked_string) {
 | 
| +  if (FLAG_fold_constants && object->IsConstant()) {
 | 
| +    HConstant* constant = HConstant::cast(object);
 | 
| +    if (constant->HasStringValue()) {
 | 
| +      return New<HConstant>(constant->StringValue()->length());
 | 
|      }
 | 
|    }
 | 
| -  return AddLoadNamedField(
 | 
| -      AddLoadNamedField(string, HObjectAccess::ForMap()),
 | 
| -      HObjectAccess::ForMapInstanceType());
 | 
| -}
 | 
| -
 | 
| -
 | 
| -HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
 | 
| -  if (string->IsConstant()) {
 | 
| -    HConstant* c_string = HConstant::cast(string);
 | 
| -    if (c_string->HasStringValue()) {
 | 
| -      return Add<HConstant>(c_string->StringValue()->length());
 | 
| -    }
 | 
| -  }
 | 
| -  return AddLoadNamedField(string, HObjectAccess::ForStringLength());
 | 
| +  return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength());
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -8608,9 +8556,13 @@ HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
 | 
|        return New<HConstant>(s->Get(i));
 | 
|      }
 | 
|    }
 | 
| -  string = BuildCheckString(string);
 | 
| -  index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
 | 
| -  return New<HStringCharCodeAt>(string, index);
 | 
| +  BuildCheckHeapObject(string);
 | 
| +  HValue* checkstring =
 | 
| +      Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
 | 
| +  HInstruction* length = BuildLoadStringLength(string, checkstring);
 | 
| +  AddInstruction(length);
 | 
| +  HInstruction* checked_index = Add<HBoundsCheck>(index, length);
 | 
| +  return New<HStringCharCodeAt>(string, checked_index);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -8741,18 +8693,10 @@ HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
 | 
|    Handle<Type> right_type = expr->right()->bounds().lower;
 | 
|    Handle<Type> result_type = expr->bounds().lower;
 | 
|    Maybe<int> fixed_right_arg = expr->fixed_right_arg();
 | 
| -  Handle<AllocationSite> allocation_site = expr->allocation_site();
 | 
| -
 | 
| -  HAllocationMode allocation_mode =
 | 
| -      FLAG_allocation_site_pretenuring
 | 
| -      ? (allocation_site.is_null()
 | 
| -         ? HAllocationMode(NOT_TENURED)
 | 
| -         : HAllocationMode(allocation_site))
 | 
| -      : HAllocationMode(isolate()->heap()->GetPretenureMode());
 | 
|  
 | 
|    HValue* result = HGraphBuilder::BuildBinaryOperation(
 | 
| -      expr->op(), left, right, left_type, right_type, result_type,
 | 
| -      fixed_right_arg, allocation_mode);
 | 
| +      expr->op(), left, right, left_type, right_type,
 | 
| +      result_type, fixed_right_arg);
 | 
|    // Add a simulate after instructions with observable side effects, and
 | 
|    // after phis, which are the result of BuildBinaryOperation when we
 | 
|    // inlined some complex subgraph.
 | 
| @@ -8772,8 +8716,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
 | 
|      Handle<Type> left_type,
 | 
|      Handle<Type> right_type,
 | 
|      Handle<Type> result_type,
 | 
| -    Maybe<int> fixed_right_arg,
 | 
| -    HAllocationMode allocation_mode) {
 | 
| +    Maybe<int> fixed_right_arg) {
 | 
|  
 | 
|    Representation left_rep = Representation::FromType(left_type);
 | 
|    Representation right_rep = Representation::FromType(right_type);
 | 
| @@ -8839,48 +8782,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
 | 
|        return AddUncasted<HInvokeFunction>(function, 2);
 | 
|      }
 | 
|  
 | 
| -    // Inline the string addition into the stub when creating allocation
 | 
| -    // mementos to gather allocation site feedback.
 | 
| -    if (graph()->info()->IsStub() &&
 | 
| -        allocation_mode.CreateAllocationMementos()) {
 | 
| -      return BuildStringAdd(left, right, allocation_mode);
 | 
| -    }
 | 
| -
 | 
| -    // Register the dependent code with the allocation site.
 | 
| -    if (!allocation_mode.feedback_site().is_null()) {
 | 
| -      ASSERT(!graph()->info()->IsStub());
 | 
| -      allocation_mode.feedback_site()->AddDependentCompilationInfo(
 | 
| -          AllocationSite::TENURING, top_info());
 | 
| -    }
 | 
| -
 | 
| -    // Inline string addition if we know that we'll create a cons string.
 | 
| -    if (left->IsConstant()) {
 | 
| -      HConstant* c_left = HConstant::cast(left);
 | 
| -      if (c_left->HasStringValue()) {
 | 
| -        int c_left_length = c_left->StringValue()->length();
 | 
| -        if (c_left_length == 0) {
 | 
| -          return right;
 | 
| -        } else if (c_left_length + 1 >= ConsString::kMinLength) {
 | 
| -          return BuildStringAdd(left, right, allocation_mode);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -    if (right->IsConstant()) {
 | 
| -      HConstant* c_right = HConstant::cast(right);
 | 
| -      if (c_right->HasStringValue()) {
 | 
| -        int c_right_length = c_right->StringValue()->length();
 | 
| -        if (c_right_length == 0) {
 | 
| -          return left;
 | 
| -        } else if (c_right_length + 1 >= ConsString::kMinLength) {
 | 
| -          return BuildStringAdd(left, right, allocation_mode);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    // Fallback to using the string add stub.
 | 
| -    return AddUncasted<HStringAdd>(
 | 
| -        left, right, allocation_mode.GetPretenureMode(),
 | 
| -        STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
 | 
| +    return AddUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_NONE);
 | 
|    }
 | 
|  
 | 
|    if (graph()->info()->IsStub()) {
 | 
| @@ -10109,7 +10011,8 @@ void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
 | 
|    CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
 | 
|    HValue* right = Pop();
 | 
|    HValue* left = Pop();
 | 
| -  HInstruction* result = NewUncasted<HStringAdd>(left, right);
 | 
| +  HInstruction* result =
 | 
| +      NewUncasted<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH);
 | 
|    return ast_context()->ReturnInstruction(result, call->id());
 | 
|  }
 | 
|  
 | 
| 
 |