1fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Redistribution and use in source and binary forms, with or without
365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// modification, are permitted provided that the following conditions are
465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// met:
565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//
665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//     * Redistributions of source code must retain the above copyright
765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       notice, this list of conditions and the following disclaimer.
865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//     * Redistributions in binary form must reproduce the above
965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       copyright notice, this list of conditions and the following
1065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       disclaimer in the documentation and/or other materials provided
1165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       with the distribution.
1265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//     * Neither the name of Google Inc. nor the names of its
1365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       contributors may be used to endorse or promote products derived
1465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//       from this software without specific prior written permission.
1565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org//
1665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "v8.h"
2965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_ARM
3165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "bootstrapper.h"
33d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org#include "code-stubs.h"
3465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "regexp-macro-assembler.h"
356bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org#include "stub-cache.h"
3665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace v8 {
3865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace internal {
3965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid ToNumberStub::InitializeInterfaceDescriptor(
42c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org    Isolate* isolate,
43c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
44c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  static Register registers[] = { r0 };
45c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  descriptor->register_param_count_ = 1;
46c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  descriptor->register_params_ = registers;
47c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  descriptor->deoptimization_handler_ = NULL;
48c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org}
49c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
50c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
51e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
52e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    Isolate* isolate,
53e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
54e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static Register registers[] = { r3, r2, r1 };
55e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  descriptor->register_param_count_ = 3;
56e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  descriptor->register_params_ = registers;
57e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  descriptor->deoptimization_handler_ =
58e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry;
59e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
60e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
61e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
6271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.orgvoid FastCloneShallowObjectStub::InitializeInterfaceDescriptor(
6371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    Isolate* isolate,
6471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
6571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  static Register registers[] = { r3, r2, r1, r0 };
6671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  descriptor->register_param_count_ = 4;
6771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  descriptor->register_params_ = registers;
6871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  descriptor->deoptimization_handler_ =
6971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org      Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
7071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org}
7171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
7271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
73bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid CreateAllocationSiteStub::InitializeInterfaceDescriptor(
74bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Isolate* isolate,
75bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
76bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  static Register registers[] = { r2 };
77bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  descriptor->register_param_count_ = 1;
78bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  descriptor->register_params_ = registers;
79bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  descriptor->deoptimization_handler_ = NULL;
80bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
81bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
82bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
83a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
84a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Isolate* isolate,
85a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
86a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static Register registers[] = { r1, r0 };
87a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  descriptor->register_param_count_ = 2;
88a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  descriptor->register_params_ = registers;
89a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  descriptor->deoptimization_handler_ =
90e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org      FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
91a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
92a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
93a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
9457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid LoadFieldStub::InitializeInterfaceDescriptor(
9557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Isolate* isolate,
9657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
9757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  static Register registers[] = { r0 };
9857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_param_count_ = 1;
9957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_params_ = registers;
10057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->deoptimization_handler_ = NULL;
10157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org}
10257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
10357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
10457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid KeyedLoadFieldStub::InitializeInterfaceDescriptor(
10557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Isolate* isolate,
10657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
10757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  static Register registers[] = { r1 };
10857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_param_count_ = 1;
10957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_params_ = registers;
11057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->deoptimization_handler_ = NULL;
11157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org}
11257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
11357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
1147bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.orgvoid KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
1157bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org    Isolate* isolate,
1167bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
1177bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  static Register registers[] = { r2, r1, r0 };
1187bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  descriptor->register_param_count_ = 3;
1197bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  descriptor->register_params_ = registers;
1207bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  descriptor->deoptimization_handler_ =
1217bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure);
1227bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org}
1237bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org
1247bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org
12594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgvoid TransitionElementsKindStub::InitializeInterfaceDescriptor(
12694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    Isolate* isolate,
12794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
12894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { r0, r1 };
12994b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  descriptor->register_param_count_ = 2;
13094b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  descriptor->register_params_ = registers;
13194b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  Address entry =
13294b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org      Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
13394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry);
13494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org}
13594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
13694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
137ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid CompareNilICStub::InitializeInterfaceDescriptor(
138ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Isolate* isolate,
1394a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
140ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  static Register registers[] = { r0 };
141ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->register_param_count_ = 1;
142ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->register_params_ = registers;
143ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->deoptimization_handler_ =
144ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      FUNCTION_ADDR(CompareNilIC_Miss);
145a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  descriptor->SetMissHandler(
146a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
147ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
148ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
149ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
150ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void InitializeArrayConstructorDescriptor(
151ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Isolate* isolate,
152ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    CodeStubInterfaceDescriptor* descriptor,
153ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    int constant_stack_parameter_count) {
1544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // register state
155ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // r0 -- number of arguments
15657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  // r1 -- function
1574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // r2 -- type info cell with elements kind
15857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  static Register registers[] = { r1, r2 };
15957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_param_count_ = 2;
160ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  if (constant_stack_parameter_count != 0) {
161ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // stack param count needs (constructor pointer, and single argument)
162ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    descriptor->stack_parameter_count_ = &r0;
163ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
164ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
1654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  descriptor->register_params_ = registers;
166f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
1674a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  descriptor->deoptimization_handler_ =
168dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
1694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
1704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
1714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
172d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgstatic void InitializeInternalArrayConstructorDescriptor(
173d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
174d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor,
175d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    int constant_stack_parameter_count) {
176d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // register state
177d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // r0 -- number of arguments
178d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // r1 -- constructor function
179d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  static Register registers[] = { r1 };
180d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->register_param_count_ = 1;
181d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
182d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  if (constant_stack_parameter_count != 0) {
183d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // stack param count needs (constructor pointer, and single argument)
184d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    descriptor->stack_parameter_count_ = &r0;
185d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
186d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
187d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->register_params_ = registers;
188d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
189d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->deoptimization_handler_ =
190dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
191d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
192d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
193d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
1944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
1954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Isolate* isolate,
1964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
197ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  InitializeArrayConstructorDescriptor(isolate, descriptor, 0);
1984a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
1994a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2004a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
2024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Isolate* isolate,
2034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
204ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  InitializeArrayConstructorDescriptor(isolate, descriptor, 1);
2054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
2064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
2094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Isolate* isolate,
2104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
211ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  InitializeArrayConstructorDescriptor(isolate, descriptor, -1);
2124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
2134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2144a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
215b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgvoid ToBooleanStub::InitializeInterfaceDescriptor(
216b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    Isolate* isolate,
217b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
218b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  static Register registers[] = { r0 };
219b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->register_param_count_ = 1;
220b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->register_params_ = registers;
221b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->deoptimization_handler_ =
222b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      FUNCTION_ADDR(ToBooleanIC_Miss);
223b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->SetMissHandler(
224b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
225b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
226b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
227b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
228d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
229d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
230d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
231d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 0);
232d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
233d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
234d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
235d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
236d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
237d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
238d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 1);
239d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
240d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
241d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
242d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
243d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
244d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
245d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1);
246d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
247d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
248d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
249e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.orgvoid StoreGlobalStub::InitializeInterfaceDescriptor(
250e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    Isolate* isolate,
251e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
252e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  static Register registers[] = { r1, r2, r0 };
253e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  descriptor->register_param_count_ = 3;
254e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  descriptor->register_params_ = registers;
255e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  descriptor->deoptimization_handler_ =
256e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      FUNCTION_ADDR(StoreIC_MissFromStubFailure);
257e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org}
258e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
259e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
260ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgvoid ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
261ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    Isolate* isolate,
262ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
263ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  static Register registers[] = { r0, r3, r1, r2 };
264ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  descriptor->register_param_count_ = 4;
265ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  descriptor->register_params_ = registers;
266ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  descriptor->deoptimization_handler_ =
267ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
268ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
269ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
270ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
27165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#define __ ACCESS_MASM(masm)
27265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
273e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
27465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitIdenticalObjectComparison(MacroAssembler* masm,
27565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Label* slow,
276fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                          Condition cond);
27765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitSmiNonsmiComparison(MacroAssembler* masm,
27865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register lhs,
27965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register rhs,
28065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Label* lhs_not_nan,
28165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Label* slow,
28265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    bool strict);
28365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
28465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           Register lhs,
28565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           Register rhs);
28665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
28765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
28877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
28977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // Update the static counter each time a new code stub is generated.
29077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  Isolate* isolate = masm->isolate();
29177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  isolate->counters()->code_stubs()->Increment();
29277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
29377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
29477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  int param_count = descriptor->register_param_count_;
29577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  {
29677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    // Call the runtime system in a fresh internal frame.
29777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
29877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    ASSERT(descriptor->register_param_count_ == 0 ||
29977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org           r0.is(descriptor->register_params_[param_count - 1]));
30077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    // Push arguments
30177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    for (int i = 0; i < param_count; ++i) {
30277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      __ push(descriptor->register_params_[i]);
30377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    }
304a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org    ExternalReference miss = descriptor->miss_handler();
30577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    __ CallExternalReference(miss, descriptor->register_param_count_);
30677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  }
30777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
30877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  __ Ret();
30977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org}
31077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
31177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
31265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FastNewClosureStub::Generate(MacroAssembler* masm) {
31365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Create a new closure from the given function info in new
31465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // space. Set the context to the current context in cp.
3155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Counters* counters = masm->isolate()->counters();
3165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
31765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label gc;
31865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
31965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Pop the function info from the stack.
32065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(r3);
32165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
32265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Attempt to allocate new JSFunction in new space.
3232bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT);
32465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r7);
3265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
327e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int map_index = Context::FunctionMapIndex(language_mode_, is_generator_);
328ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
32946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Compute the function map in the current native context and set that
33065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // as the map of the allocated object.
33146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
33246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
3335a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ ldr(r5, MemOperand(r2, Context::SlotOffset(map_index)));
3345a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ str(r5, FieldMemOperand(r0, HeapObject::kMapOffset));
33565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
33665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Initialize the rest of the function. We don't have to update the
33765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // write barrier because the allocated object is in new space.
33865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex);
3395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
34065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, FieldMemOperand(r0, JSObject::kPropertiesOffset));
34165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, FieldMemOperand(r0, JSObject::kElementsOffset));
3425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ str(r5, FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset));
34365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
34465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
34565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
346a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
34765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Initialize the code pointer in the function to be the one
34865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // found in the shared function info object.
3495a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // But first check if there is an optimized version for our context.
3505a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Label check_optimized;
3515a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Label install_unoptimized;
3525a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  if (FLAG_cache_optimized_code) {
3535a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    __ ldr(r1,
3545a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org           FieldMemOperand(r3, SharedFunctionInfo::kOptimizedCodeMapOffset));
3555a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    __ tst(r1, r1);
3565a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    __ b(ne, &check_optimized);
3575a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  }
3585a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ bind(&install_unoptimized);
3595a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
3605a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
36165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
36265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
36365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
36465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
36565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return result. The argument function info has been popped already.
36665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
36765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3685a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ bind(&check_optimized);
3695a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
3705a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r6, r7);
3715a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
37246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // r2 holds native context, r1 points to fixed array of 3-element entries
37346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // (native context, optimized code, literals).
3745a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // The optimized code map must never be empty, so check the first elements.
3755a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Label install_optimized;
3765a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Speculatively move code object into r4.
3774e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ ldr(r4, FieldMemOperand(r1, SharedFunctionInfo::kFirstCodeSlot));
3784e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ ldr(r5, FieldMemOperand(r1, SharedFunctionInfo::kFirstContextSlot));
3795a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ cmp(r2, r5);
3805a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ b(eq, &install_optimized);
3815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
3825a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Iterate through the rest of map backwards.  r4 holds an index as a Smi.
3835a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Label loop;
3845a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ ldr(r4, FieldMemOperand(r1, FixedArray::kLengthOffset));
3855a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ bind(&loop);
3865a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Do not double check first entry.
3874e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ cmp(r4, Operand(Smi::FromInt(SharedFunctionInfo::kSecondEntryIndex)));
3885a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ b(eq, &install_unoptimized);
3894e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ sub(r4, r4, Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
3905a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
391bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
3925a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ ldr(r5, MemOperand(r5));
3935a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ cmp(r2, r5);
3945a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ b(ne, &loop);
3955a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Hit: fetch the optimized code.
3965a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
397bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4));
3985a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ add(r5, r5, Operand(kPointerSize));
3995a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ ldr(r4, MemOperand(r5));
4005a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
4015a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ bind(&install_optimized);
4025a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ IncrementCounter(counters->fast_new_closure_install_optimized(),
4035a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                      1, r6, r7);
4045a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
4055a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // TODO(fschneider): Idea: store proper code pointers in the map and either
4065a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // unmangle them on marking or do nothing as the whole map is discarded on
4075a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // major GC anyway.
4085a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
4095a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ str(r4, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
4105a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
4115a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Now link a function into a list of optimized functions.
4125a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ ldr(r4, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
4135a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
4145a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset));
4155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // No need for write barrier as JSFunction (eax) is in the new space.
4165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
4175a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ str(r0, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST));
4185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Store JSFunction (eax) into edx before issuing write barrier as
4195a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // it clobbers all the registers passed.
4205a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ mov(r4, r0);
4215a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ RecordWriteContextSlot(
4225a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      r2,
4235a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST),
4245a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      r4,
4255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      r1,
4265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      kLRHasNotBeenSaved,
4275a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      kDontSaveFPRegs);
4285a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
4295a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Return result. The argument function info has been popped already.
4305a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ Ret();
4315a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
43265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Create a new closure through the slower runtime call.
43365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&gc);
43421b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  __ LoadRoot(r4, Heap::kFalseValueRootIndex);
43521b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  __ Push(cp, r3, r4);
43621b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org  __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
43765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
43865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
43965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
44065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FastNewContextStub::Generate(MacroAssembler* masm) {
44165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Try to allocate the context in new space.
44265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label gc;
4430ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
44465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
44565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Attempt to allocate the context in new space.
4462bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT);
44765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
44865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load the function from the stack.
44965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, MemOperand(sp, 0));
45065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
451f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the object header.
452fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ LoadRoot(r1, Heap::kFunctionContextMapRootIndex);
4530ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  __ mov(r2, Operand(Smi::FromInt(length)));
45465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset));
455fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
45665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
457fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Set up the fixed slots, copy the global object from the previous context.
45846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
45965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r1, Operand(Smi::FromInt(0)));
46065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX)));
4616d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
46265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX)));
46346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ str(r2, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
46465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
46565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Initialize the rest of the slots to undefined.
46665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
4670ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
46865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ str(r1, MemOperand(r0, Context::SlotOffset(i)));
46965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
47065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
47165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Remove the on-stack argument and return.
47265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(cp, r0);
47365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop();
47465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
47565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
47665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Need to collect. Call into runtime system.
47765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&gc);
4786d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
47965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
48065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
48165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
482a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.orgvoid FastNewBlockContextStub::Generate(MacroAssembler* masm) {
483a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Stack layout on entry:
484a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  //
485a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // [sp]: function.
486a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // [sp + kPointerSize]: serialized scope info
487a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
488a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Try to allocate the context in new space.
489a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  Label gc;
490a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
4912bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT);
492a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
493a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Load the function from the stack.
494a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ ldr(r3, MemOperand(sp, 0));
495a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
496a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Load the serialized scope info from the stack.
497a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
498a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
499f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the object header.
500a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ LoadRoot(r2, Heap::kBlockContextMapRootIndex);
501a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
502a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(r2, Operand(Smi::FromInt(length)));
503a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset));
504a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
50546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // If this block context is nested in the native context we get a smi
506a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // sentinel instead of a function. The block context should get the
50746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // canonical empty function of the native context as its closure which
508a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // we still have to look up.
509a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  Label after_sentinel;
510a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ JumpIfNotSmi(r3, &after_sentinel);
511a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  if (FLAG_debug_code) {
512a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    __ cmp(r3, Operand::Zero());
513594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kExpected0AsASmiSentinel);
514a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  }
515a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ ldr(r3, GlobalObjectOperand());
51646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
517a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ ldr(r3, ContextOperand(r3, Context::CLOSURE_INDEX));
518a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ bind(&after_sentinel);
519a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
520fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Set up the fixed slots, copy the global object from the previous context.
52146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
522a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ str(r3, ContextOperand(r0, Context::CLOSURE_INDEX));
523a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ str(cp, ContextOperand(r0, Context::PREVIOUS_INDEX));
524a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ str(r1, ContextOperand(r0, Context::EXTENSION_INDEX));
52546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ str(r2, ContextOperand(r0, Context::GLOBAL_OBJECT_INDEX));
526a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
527a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Initialize the rest of the slots to the hole value.
528a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
529a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  for (int i = 0; i < slots_; i++) {
530a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    __ str(r1, ContextOperand(r0, i + Context::MIN_CONTEXT_SLOTS));
531a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  }
532a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
533a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Remove the on-stack argument and return.
534a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(cp, r0);
535a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
536a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ Ret();
537a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
538a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Need to collect. Call into runtime system.
539a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ bind(&gc);
540a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
541a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org}
542a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
543a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
54465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Takes a Smi and converts to an IEEE 64 bit floating point value in two
54565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// registers.  The format is 1 sign bit, 11 exponent bits (biased 1023) and
54665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// 52 fraction bits (20 in the first word, 32 in the second).  Zeros is a
54765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// scratch register.  Destroys the source register.  No GC occurs during this
54865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// stub so you don't have to set up the frame.
549a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass ConvertToDoubleStub : public PlatformCodeStub {
55065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
55165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ConvertToDoubleStub(Register result_reg_1,
55265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      Register result_reg_2,
55365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      Register source_reg,
55465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      Register scratch_reg)
55565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      : result1_(result_reg_1),
55665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        result2_(result_reg_2),
55765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        source_(source_reg),
55865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        zeros_(scratch_reg) { }
55965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
56065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org private:
56165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register result1_;
56265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register result2_;
56365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register source_;
56465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register zeros_;
56565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
56665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Minor key encoding in 16 bits.
56765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
56865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  class OpBits: public BitField<Token::Value, 2, 14> {};
56965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
57065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Major MajorKey() { return ConvertToDouble; }
57165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int MinorKey() {
57265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Encode the parameters in a unique 16 bit value.
57365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    return  result1_.code() +
57465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org           (result2_.code() << 4) +
57565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org           (source_.code() << 8) +
57665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org           (zeros_.code() << 12);
57765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
57865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
57965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  void Generate(MacroAssembler* masm);
58065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
58165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
58265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
58365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid ConvertToDoubleStub::Generate(MacroAssembler* masm) {
584160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Register exponent = result1_;
585160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Register mantissa = result2_;
58644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org
58765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label not_special;
588bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(source_);
58965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Move sign bit from source to destination.  This works because the sign bit
59065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // in the exponent word of the double has the same position and polarity as
59165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // the 2's complement sign bit in a Smi.
59265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
59365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC);
59465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Subtract from 0 if source was negative.
59559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ rsb(source_, source_, Operand::Zero(), LeaveCC, ne);
59665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
59765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // We have -1, 0 or 1, which we treat specially. Register source_ contains
59865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // absolute value: it is either equal to 1 (special case of -1 and 1),
59965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // greater than 1 (not a special case) or less than 1 (special case of 0).
60065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(source_, Operand(1));
60165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(gt, &not_special);
60265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
60365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // For 1 or -1 we need to or in the 0 exponent (biased to 1023).
6041456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const uint32_t exponent_word_for_1 =
60565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      HeapNumber::kExponentBias << HeapNumber::kExponentShift;
60665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq);
60765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // 1, 0 and -1 all have 0 for the second word.
60859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(mantissa, Operand::Zero());
60965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
61065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
61165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_special);
612b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org  __ clz(zeros_, source_);
61365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Compute exponent and or it into the exponent register.
61465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // We use mantissa as a scratch register here.  Use a fudge factor to
61565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts
61665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // that fit in the ARM's constant field.
61765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int fudge = 0x400;
61865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias - fudge));
61965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(mantissa, mantissa, Operand(fudge));
62065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(exponent,
62165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         exponent,
62265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Operand(mantissa, LSL, HeapNumber::kExponentShift));
62365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Shift up the source chopping the top bit off.
62465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(zeros_, zeros_, Operand(1));
62565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0.
62665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(source_, Operand(source_, LSL, zeros_));
62765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Compute lower part of fraction (last 12 bits).
62865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord));
62965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // And the top (top 20 bits).
63065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(exponent,
63165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         exponent,
63265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord));
63365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
63465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
63565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
63665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool WriteInt32ToHeapNumberStub::IsPregenerated() {
638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // These variants are compiled ahead of time.  See next method.
639c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) {
640c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return true;
641c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
642c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (the_int_.is(r2) && the_heap_number_.is(r0) && scratch_.is(r3)) {
643c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return true;
644c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
645c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Other register combinations are generated as and when they are needed,
646c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // so it is unsafe to call them from stubs (we can't generate a stub while
647c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // we are generating a stub).
648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return false;
649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6528432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(
6538432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Isolate* isolate) {
654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  WriteInt32ToHeapNumberStub stub1(r1, r0, r2);
655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  WriteInt32ToHeapNumberStub stub2(r2, r0, r3);
6568432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  stub1.GetCode(isolate)->set_is_pregenerated(true);
6578432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  stub2.GetCode(isolate)->set_is_pregenerated(true);
658c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
659c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
660c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
66165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment for class.
66265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
66365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label max_negative_int;
66465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // the_int_ has the answer which is a signed int32 but not a Smi.
66565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // We test for the special value that has a different exponent.  This test
66665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // has the neat side effect of setting the flags according to the sign.
66765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
66865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(the_int_, Operand(0x80000000u));
66965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &max_negative_int);
67065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Set up the correct exponent in scratch_.  All non-Smi int32s have the same.
67165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).
67265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  uint32_t non_smi_exponent =
67365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
67465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch_, Operand(non_smi_exponent));
67565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Set the sign bit in scratch_ if the value was negative.
67665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs);
67765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Subtract from 0 if the value was negative.
67859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ rsb(the_int_, the_int_, Operand::Zero(), LeaveCC, cs);
67965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // We should be masking the implict first digit of the mantissa away here,
68065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // but it just ends up combining harmlessly with the last digit of the
68165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // exponent that happens to be 1.  The sign bit is 0 so we shift 10 to get
68265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // the most significant 1 to hit the last bit of the 12 bit sign and exponent.
68365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0);
68465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
68565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance));
68665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(scratch_, FieldMemOperand(the_heap_number_,
68765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                   HeapNumber::kExponentOffset));
68865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance));
68965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(scratch_, FieldMemOperand(the_heap_number_,
69065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                   HeapNumber::kMantissaOffset));
69165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
69265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
69365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&max_negative_int);
69465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The max negative int32 is stored as a positive number in the mantissa of
69565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // a double because it uses a sign bit instead of using two's complement.
69665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The actual mantissa bits stored are all 0 because the implicit most
69765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // significant 1 bit is not stored.
69865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  non_smi_exponent += 1 << HeapNumber::kExponentShift;
69965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent));
70065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset));
70159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(ip, Operand::Zero());
70265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset));
70365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
70465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
70565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
70665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
70765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Handle the case where the lhs and rhs are the same object.
70865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Equality is almost reflexive (everything but NaN), so this is a test
70965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// for "identity and not NaN".
71065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitIdenticalObjectComparison(MacroAssembler* masm,
71165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Label* slow,
712fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                          Condition cond) {
71365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label not_identical;
71465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label heap_number, return_equal;
71565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r0, r1);
71665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &not_identical);
71765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
718d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
719fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // so we do the second best thing - test it ourselves.
720fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // They are both equal and they are not both Smis so both of them are not
721fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // Smis.  If it's not a heap number, then return equal.
722fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cond == lt || cond == gt) {
723fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ CompareObjectType(r0, r4, r4, FIRST_SPEC_OBJECT_TYPE);
724fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ b(ge, slow);
725fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  } else {
726fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
727fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ b(eq, &heap_number);
728fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Comparing JS objects with <=, >= is complicated.
729fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    if (cond != eq) {
730fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ cmp(r4, Operand(FIRST_SPEC_OBJECT_TYPE));
73165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ b(ge, slow);
732fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Normally here we fall through to return_equal, but undefined is
733fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // special: (undefined == undefined) == true, but
734fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // (undefined <= undefined) == false!  See ECMAScript 11.8.5.
735fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      if (cond == le || cond == ge) {
736fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ cmp(r4, Operand(ODDBALL_TYPE));
737fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ b(ne, &return_equal);
738fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
739fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ cmp(r0, r2);
740fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ b(ne, &return_equal);
741fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        if (cond == le) {
742fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org          // undefined <= undefined should fail.
743fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org          __ mov(r0, Operand(GREATER));
744fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        } else  {
745fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org          // undefined >= undefined should fail.
746fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org          __ mov(r0, Operand(LESS));
74765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        }
748fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ Ret();
74965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      }
75065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
75165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
75265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
75365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&return_equal);
754378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  if (cond == lt) {
75565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r0, Operand(GREATER));  // Things aren't less than themselves.
756378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  } else if (cond == gt) {
75765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r0, Operand(LESS));     // Things aren't greater than themselves.
75865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
75965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r0, Operand(EQUAL));    // Things are <=, >=, ==, === themselves.
76065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
76165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
76265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
763fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // For less and greater we don't have to check for NaN since the result of
764fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // x < x is false regardless.  For the others here is some code to check
765fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // for NaN.
766fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cond != lt && cond != gt) {
767fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&heap_number);
768fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // It is a heap number, so return non-equal if it's NaN and equal if it's
769fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // not NaN.
770fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
771fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // The representation of NaN values has all exponent bits (52..62) set,
772fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // and not all mantissa bits (0..51) clear.
773fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Read top bits of double representation (second word of value).
774fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
775fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Test that exponent bits are all set.
776fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
777fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // NaNs have all-one exponents so they sign extend to -1.
778fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(r3, Operand(-1));
779fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ b(ne, &return_equal);
780fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
781fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Shift out flag and all exponent bits, retaining only mantissa.
782fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord));
783fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Or with all low-bits of mantissa.
784fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
785fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ orr(r0, r3, Operand(r2), SetCC);
786fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // For equal we already have the right value in r0:  Return zero (equal)
787fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // if all bits in mantissa are zero (it's an Infinity) and non-zero if
788fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // not (it's a NaN).  For <= and >= we need to load r0 with the failing
789fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // value if it's a NaN.
790fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    if (cond != eq) {
791fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // All-zero means Infinity means equal.
792fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ Ret(eq);
793fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      if (cond == le) {
794fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ mov(r0, Operand(GREATER));  // NaN <= NaN should fail.
795fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      } else {
796fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ mov(r0, Operand(LESS));     // NaN >= NaN should fail.
79765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      }
79865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
799fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ Ret();
80065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
801fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // No fall through here.
80265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
80365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_identical);
80465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
80565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
80665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
80765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment at call site.
80865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitSmiNonsmiComparison(MacroAssembler* masm,
80965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register lhs,
81065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register rhs,
81165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Label* lhs_not_nan,
81265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Label* slow,
81365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    bool strict) {
81465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT((lhs.is(r0) && rhs.is(r1)) ||
81565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         (lhs.is(r1) && rhs.is(r0)));
81665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
81765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label rhs_is_smi;
8187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(rhs, &rhs_is_smi);
81965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
82065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Lhs is a Smi.  Check whether the rhs is a heap number.
82165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
82265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (strict) {
82365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If rhs is not a number and lhs is a Smi then strict equality cannot
82465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // succeed.  Return non-equal
82565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If rhs is r0 then there is already a non zero value in it.
82665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (!rhs.is(r0)) {
82765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
82865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
82965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Ret(ne);
83065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
83165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Smi compared non-strictly with a non-Smi non-heap-number.  Call
83265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // the runtime.
83365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ne, slow);
83465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
83565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
83665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Lhs is a smi, rhs is a number.
837e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Convert lhs to a double in d7.
838bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiToDouble(d7, lhs);
839e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Load the double from rhs, tagged HeapNumber r0, to d6.
840e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(r7, rhs, Operand(kHeapObjectTag));
841e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldr(d6, r7, HeapNumber::kValueOffset);
84265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
84365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // We now have both loaded as doubles but we can skip the lhs nan check
84465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // since it's a smi.
84565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(lhs_not_nan);
84665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
84765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&rhs_is_smi);
84865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Rhs is a smi.  Check whether the non-smi lhs is a heap number.
84965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
85065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (strict) {
85165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If lhs is not a number and rhs is a smi then strict equality cannot
85265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // succeed.  Return non-equal.
85365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If lhs is r0 then there is already a non zero value in it.
85465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (!lhs.is(r0)) {
85565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
85665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
85765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Ret(ne);
85865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
85965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Smi compared non-strictly with a non-smi non-heap-number.  Call
86065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // the runtime.
86165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ne, slow);
86265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
86365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
86465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Rhs is a smi, lhs is a heap number.
865e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Load the double from lhs, tagged HeapNumber r1, to d7.
866e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(r7, lhs, Operand(kHeapObjectTag));
867e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldr(d7, r7, HeapNumber::kValueOffset);
868e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Convert rhs to a double in d6              .
869bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiToDouble(d6, rhs);
87065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fall through to both_loaded_as_doubles.
87165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
87265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
87365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
87465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment at call site.
87565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
87665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           Register lhs,
87765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           Register rhs) {
87865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    ASSERT((lhs.is(r0) && rhs.is(r1)) ||
87965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org           (lhs.is(r1) && rhs.is(r0)));
88065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
881d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    // If either operand is a JS object or an oddball value, then they are
88265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // not equal since their pointers are different.
88365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // There is no test for undetectability in strict equality.
884c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
88565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label first_non_object;
88665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Get the type of the first operand into r2 and compare it with
887d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    // FIRST_SPEC_OBJECT_TYPE.
888d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CompareObjectType(rhs, r2, r2, FIRST_SPEC_OBJECT_TYPE);
88965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(lt, &first_non_object);
89065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
89165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Return non-zero (r0 is not zero)
89265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label return_not_equal;
89365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&return_not_equal);
89465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Ret();
89565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
89665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&first_non_object);
89765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for oddballs: true, false, null, undefined.
89865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(r2, Operand(ODDBALL_TYPE));
89965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(eq, &return_not_equal);
90065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
901d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE);
90265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ge, &return_not_equal);
90365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
90465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for oddballs: true, false, null, undefined.
90565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(r3, Operand(ODDBALL_TYPE));
90665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(eq, &return_not_equal);
90765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
9084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Now that we have the types we might as well check for
9094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // internalized-internalized.
910ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
911ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ orr(r2, r2, Operand(r3));
912ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ tst(r2, Operand(kIsNotStringMask | kIsNotInternalizedMask));
913ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ b(eq, &return_not_equal);
91465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
91565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
91665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
91765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment at call site.
91865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
91965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register lhs,
92065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register rhs,
92165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Label* both_loaded_as_doubles,
92265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Label* not_heap_numbers,
92365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Label* slow) {
92465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT((lhs.is(r0) && rhs.is(r1)) ||
92565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         (lhs.is(r1) && rhs.is(r0)));
92665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
92765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE);
92865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, not_heap_numbers);
92965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset));
93065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r2, r3);
93165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, slow);  // First was a heap number, second wasn't.  Go slow case.
93265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
93365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Both are heap numbers.  Load them up then jump to the code we have
93465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // for that.
935e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(r7, rhs, Operand(kHeapObjectTag));
936e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldr(d6, r7, HeapNumber::kValueOffset);
937e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(r7, lhs, Operand(kHeapObjectTag));
938e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldr(d7, r7, HeapNumber::kValueOffset);
93965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(both_loaded_as_doubles);
94065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
94165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
94265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
9434a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org// Fast negative check for internalized-to-internalized equality.
9444a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgstatic void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
9454a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                                     Register lhs,
9464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                                     Register rhs,
9474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                                     Label* possible_strings,
9484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                                     Label* not_both_strings) {
94965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT((lhs.is(r0) && rhs.is(r1)) ||
95065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         (lhs.is(r1) && rhs.is(r0)));
95165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
95265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2 is object type of rhs.
95365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label object_test;
954ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
95565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r2, Operand(kIsNotStringMask));
95665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &object_test);
957ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ tst(r2, Operand(kIsNotInternalizedMask));
958ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ b(ne, possible_strings);
95965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
96065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ge, not_both_strings);
961ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ tst(r3, Operand(kIsNotInternalizedMask));
962ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ b(ne, possible_strings);
96365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
9644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Both are internalized.  We already checked they weren't the same pointer
96565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // so they are not equal.
96665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(NOT_EQUAL));
96765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
96865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
96965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&object_test);
970d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE));
97165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(lt, not_both_strings);
972d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE);
97365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(lt, not_both_strings);
97465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If both objects are undetectable, they are equal. Otherwise, they
97565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // are not equal, since they are different objects and an object is not
97665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // equal to undefined.
97765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset));
97865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset));
97965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
98065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(r0, r2, Operand(r3));
98165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
98265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ eor(r0, r0, Operand(1 << Map::kIsUndetectable));
98365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
98465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
98565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
98665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
98765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
98865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                         Register object,
98965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                         Register result,
99065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                         Register scratch1,
99165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                         Register scratch2,
99265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                         Register scratch3,
99365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                         Label* not_found) {
99465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Use of registers. Register result is used as a temporary.
99565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register number_string_cache = result;
99665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register mask = scratch3;
99765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
99865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load the number string cache.
99965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
100065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
100165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make the hash mask from the length of the number string cache. It
100265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // contains two elements (number and string) for each cache entry.
100365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
100465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Divide length by two (length is a smi).
100565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1));
100665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(mask, mask, Operand(1));  // Make mask.
100765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
100865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate the entry in the number string cache. The hash value in the
100965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // number string cache for smis is just the smi value, and the hash for
101065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // doubles is the xor of the upper and lower words. See
101165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Heap::GetNumberStringCache.
10127979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Isolate* isolate = masm->isolate();
101365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label is_smi;
101465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label load_result_from_cache;
1015ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ JumpIfSmi(object, &is_smi);
1016ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ CheckMap(object,
1017ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org              scratch1,
1018ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org              Heap::kHeapNumberMapRootIndex,
1019ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org              not_found,
1020ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org              DONT_DO_SMI_CHECK);
1021e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
1022ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  STATIC_ASSERT(8 == kDoubleSize);
1023ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ add(scratch1,
1024ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org          object,
1025ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org          Operand(HeapNumber::kValueOffset - kHeapObjectTag));
1026ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit());
1027ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ eor(scratch1, scratch1, Operand(scratch2));
1028ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ and_(scratch1, scratch1, Operand(mask));
1029ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
1030ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Calculate address of entry in string cache: each entry consists
1031ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // of two pointer sized fields.
1032ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ add(scratch1,
1033ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org          number_string_cache,
1034ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org          Operand(scratch1, LSL, kPointerSizeLog2 + 1));
1035ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
1036ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  Register probe = mask;
1037ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ ldr(probe,
1038ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org          FieldMemOperand(scratch1, FixedArray::kHeaderSize));
1039ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ JumpIfSmi(probe, not_found);
1040ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ sub(scratch2, object, Operand(kHeapObjectTag));
1041ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ vldr(d0, scratch2, HeapNumber::kValueOffset);
1042ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ sub(probe, probe, Operand(kHeapObjectTag));
1043ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ vldr(d1, probe, HeapNumber::kValueOffset);
1044ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ VFPCompareAndSetFlags(d0, d1);
1045ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ b(ne, not_found);  // The cache did not contain this value.
1046ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ b(&load_result_from_cache);
104765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
104865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&is_smi);
104965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register scratch = scratch1;
105065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(scratch, mask, Operand(object, ASR, 1));
105165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate address of entry in string cache: each entry consists
105265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // of two pointer sized fields.
105365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(scratch,
105465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         number_string_cache,
105565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Operand(scratch, LSL, kPointerSizeLog2 + 1));
105665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
105765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if the entry is the smi we are looking for.
105865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
105965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(object, probe);
106065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, not_found);
106165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
106265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the result from the cache.
106365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&load_result_from_cache);
106465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(result,
106565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
10667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(isolate->counters()->number_to_string_native(),
106765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      1,
106865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      scratch1,
106965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      scratch2);
107065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
107165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
107265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
107365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid NumberToStringStub::Generate(MacroAssembler* masm) {
107465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime;
107565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
107665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r1, MemOperand(sp, 0));
107765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
107865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Generate code to lookup number in the number string cache.
1079ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, &runtime);
108065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(1 * kPointerSize));
108165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
108265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
108365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
108465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle number to string in the runtime system if not found in the cache.
108565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
108665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
108765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
108865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1089fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgstatic void ICCompareStub_CheckInputType(MacroAssembler* masm,
1090fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                         Register input,
1091fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                         Register scratch,
1092fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                         CompareIC::State expected,
1093fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                         Label* fail) {
1094fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label ok;
1095fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (expected == CompareIC::SMI) {
1096fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(input, fail);
10978432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  } else if (expected == CompareIC::NUMBER) {
1098fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(input, &ok);
1099fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
1100fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                DONT_DO_SMI_CHECK);
1101fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
11024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // We could be strict about internalized/non-internalized here, but as long as
1103fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // hydrogen doesn't care, the stub doesn't have to care either.
1104fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&ok);
1105fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}
1106fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1107fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1108fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org// On entry r1 and r2 are the values to be compared.
110965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// On exit r0 is 0, positive or negative to indicate the result of
111065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// the comparison.
1111fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
1112fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Register lhs = r1;
1113fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Register rhs = r0;
1114fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Condition cc = GetCondition();
1115fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1116fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label miss;
1117fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ICCompareStub_CheckInputType(masm, lhs, r2, left_, &miss);
1118fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ICCompareStub_CheckInputType(masm, rhs, r3, right_, &miss);
111965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
112065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label slow;  // Call builtin.
112165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label not_smis, both_loaded_as_doubles, lhs_not_nan;
112265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1123fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label not_two_smis, smi_done;
1124fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ orr(r2, r1, r0);
1125fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ JumpIfNotSmi(r2, &not_two_smis);
1126fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ mov(r1, Operand(r1, ASR, 1));
1127fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ sub(r0, r1, Operand(r0, ASR, 1));
1128fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ Ret();
1129fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&not_two_smis);
1130d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
113165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // NOTICE! This code is only reached after a smi-fast-case check, so
113265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // it is certain that at least one operand isn't a smi.
113365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
113465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle the case where the objects are identical.  Either returns the answer
113565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // or goes to slow.  Only falls through if the objects were not identical.
1136fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  EmitIdenticalObjectComparison(masm, &slow, cc);
113765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
113865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If either is a Smi (we know that not both are), then they can only
113965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // be strictly equal if the other is a HeapNumber.
114065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
114165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT_EQ(0, Smi::FromInt(0));
1142fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ and_(r2, lhs, Operand(rhs));
11437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(r2, &not_smis);
114465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // One operand is a smi.  EmitSmiNonsmiComparison generates code that can:
114565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // 1) Return the answer.
114665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // 2) Go to slow.
114765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // 3) Fall through to both_loaded_as_doubles.
114865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // 4) Jump to lhs_not_nan.
114965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // In cases 3 and 4 we have found out we were dealing with a number-number
115065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // comparison.  If VFP3 is supported the double values of the numbers have
115165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // been loaded into d7 and d6.  Otherwise, the double values have been loaded
115265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // into r0, r1, r2, and r3.
1153fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict());
115465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
115565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&both_loaded_as_doubles);
115665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The arguments have been converted to doubles and stored in d6 and d7, if
115765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // VFP3 is supported, or in r0, r1, r2, and r3.
11587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Isolate* isolate = masm->isolate();
1159e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&lhs_not_nan);
1160e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label no_nan;
1161e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // ARMv7 VFP3 instructions to implement double precision comparison.
1162e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ VFPCompareAndSetFlags(d7, d6);
1163e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label nan;
1164e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ b(vs, &nan);
1165e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r0, Operand(EQUAL), LeaveCC, eq);
1166e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r0, Operand(LESS), LeaveCC, lt);
1167e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r0, Operand(GREATER), LeaveCC, gt);
1168e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Ret();
116965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1170e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&nan);
1171e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // If one of the sides was a NaN then the v flag is set.  Load r0 with
1172e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // whatever it takes to make the comparison fail, since comparisons with NaN
1173e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // always fail.
1174e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (cc == lt || cc == le) {
1175e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ mov(r0, Operand(GREATER));
117665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
1177e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ mov(r0, Operand(LESS));
117865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
1179e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Ret();
118065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
118165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_smis);
118265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // At this point we know we are dealing with two different objects,
118365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // and neither of them is a Smi.  The objects are in rhs_ and lhs_.
1184fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (strict()) {
118565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // This returns non-equal for some object types, or falls through if it
118665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // was not lucky.
1187fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
118865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
118965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
11904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label check_for_internalized_strings;
119165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label flat_string_check;
119265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check for heap-number-heap-number comparison.  Can jump to slow case,
119365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // or load both doubles into r0, r1, r2, r3 and jump to the code that handles
11944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // that case.  If the inputs are not doubles then jumps to
11954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // check_for_internalized_strings.
119665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // In this case r2 will contain the type of rhs_.  Never falls through.
119765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  EmitCheckForTwoHeapNumbers(masm,
1198fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                             lhs,
1199fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                             rhs,
120065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                             &both_loaded_as_doubles,
12014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                             &check_for_internalized_strings,
120265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                             &flat_string_check);
120365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
12044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&check_for_internalized_strings);
120565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
12064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // internalized strings.
1207fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == eq && !strict()) {
12084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Returns an answer for two internalized strings or two detectable objects.
120965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Otherwise jumps to string case or not both strings case.
121065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Assumes that r2 is the type of rhs_ on entry.
12114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    EmitCheckForInternalizedStringsOrObjects(
12124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org        masm, lhs, rhs, &flat_string_check, &slow);
121365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
121465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
121565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check for both being sequential ASCII strings, and inline if that is the
121665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // case.
121765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&flat_string_check);
121865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1219fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, r2, r3, &slow);
122065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
12217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3);
1222fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == eq) {
12231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    StringCompareStub::GenerateFlatAsciiStringEquals(masm,
1224fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                     lhs,
1225fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                     rhs,
122665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                     r2,
122765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                     r3,
12281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                     r4);
12291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  } else {
12301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
1231fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                       lhs,
1232fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                       rhs,
12331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       r2,
12341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       r3,
12351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       r4,
12361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       r5);
12371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
123865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Never falls through to here.
123965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
124065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow);
124165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1242fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ Push(lhs, rhs);
124365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Figure out which native to call and setup the arguments.
124465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Builtins::JavaScript native;
1245fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == eq) {
1246fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
124765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
124865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    native = Builtins::COMPARE;
124965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    int ncr;  // NaN compare result
1250fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    if (cc == lt || cc == le) {
125165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      ncr = GREATER;
125265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    } else {
1253fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      ASSERT(cc == gt || cc == ge);  // remaining cases
125465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      ncr = LESS;
125565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
125665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r0, Operand(Smi::FromInt(ncr)));
125765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ push(r0);
125865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
125965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
126065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
126165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // tagged as a small integer.
12628e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  __ InvokeBuiltin(native, JUMP_FUNCTION);
1263fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1264fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&miss);
1265fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  GenerateMiss(masm);
126665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
126765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
126865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
1270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We don't allow a GC during a store buffer overflow so there is no need to
1271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // store the registers in any particular way, but we do have to store and
1272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // restore them.
1273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ stm(db_w, sp, kCallerSaved | lr.bit());
1274003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
1275003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org  const Register scratch = r1;
1276003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
1277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (save_doubles_ == kSaveFPRegs) {
127877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    __ SaveFPRegs(sp, scratch);
1279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
1280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  const int argument_count = 1;
1281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  const int fp_argument_count = 0;
1282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  AllowExternalCallThatCantCauseGC scope(masm);
1284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
128532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ mov(r0, Operand(ExternalReference::isolate_address(masm->isolate())));
1286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ CallCFunction(
1287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference::store_buffer_overflow_function(masm->isolate()),
1288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      argument_count);
1289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (save_doubles_ == kSaveFPRegs) {
129077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    __ RestoreFPRegs(sp, scratch);
1291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
1292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ ldm(ia_w, sp, kCallerSaved | pc.bit());  // Also pop pc to get Ret(0).
1293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
1294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
129632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Generates code to call a C function to do a double operation.
129732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// This code never falls through, but returns with a heap number containing
129832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// the result in r0.
129932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Register heapnumber_result must be a heap number in which the
130032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// result of the operation will be stored.
130132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Requires the following layout on entry:
130232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// d0: Left value.
130332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// d1: Right value.
130432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// If soft float ABI, use also r0, r1, r2, r3.
130532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.orgstatic void CallCCodeForDoubleOperation(MacroAssembler* masm,
130632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                        Token::Value op,
130732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                        Register heap_number_result,
130832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                        Register scratch) {
130932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // Assert that heap_number_result is callee-saved.
131032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // We currently always use r5 to pass it.
131132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  ASSERT(heap_number_result.is(r5));
131232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org
131332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // Push the current return address before the C call. Return will be
131432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // through pop(pc) below.
131532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ push(lr);
131632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ PrepareCallCFunction(0, 2, scratch);
131732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  if (!masm->use_eabi_hardfloat()) {
131832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ vmov(r0, r1, d0);
131932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ vmov(r2, r3, d1);
132032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  }
132132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  {
132232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    AllowExternalCallThatCantCauseGC scope(masm);
132332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ CallCFunction(
132432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org         ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
132532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  }
132632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // Store answer in the overwritable heap number. Double returned in
132732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // registers r0 and r1 or in d0.
132832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  if (masm->use_eabi_hardfloat()) {
132932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ vstr(d0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
133032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  } else {
133132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ Strd(r0, r1,
133232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
133332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  }
133432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  // Place heap_number_result in r0 and return to the pushed return address.
133532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ mov(r0, Operand(heap_number_result));
133632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ pop(pc);
133732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org}
133832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org
133932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org
1340fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub::Initialize() {
1341e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  platform_specific_bit_ = true;  // VFP2 is a base requirement for V8
1342fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}
1343fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1344fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
134540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
1346378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Label get_result;
1347378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1348378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ Push(r1, r0);
1349378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1350378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ mov(r2, Operand(Smi::FromInt(MinorKey())));
1351fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ push(r2);
1352378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1353378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ TailCallExternalReference(
135440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
1355ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                        masm->isolate()),
1356fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      3,
1357378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      1);
1358378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
1359378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1360378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
136140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
1362378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    MacroAssembler* masm) {
1363a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  UNIMPLEMENTED();
1364378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
1365378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1366378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1367fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
1368fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                          Token::Value op) {
1369378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register left = r1;
1370378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register right = r0;
1371378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register scratch1 = r7;
1372378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register scratch2 = r9;
1373378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1374378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  ASSERT(right.is(r0));
1375378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  STATIC_ASSERT(kSmiTag == 0);
1376378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1377378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Label not_smi_result;
1378fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  switch (op) {
1379378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    case Token::ADD:
1380378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ add(right, left, Operand(right), SetCC);  // Add optimistically.
1381378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ Ret(vc);
1382378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ sub(right, right, Operand(left));  // Revert optimistic add.
1383378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      break;
1384378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    case Token::SUB:
1385378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ sub(right, left, Operand(right), SetCC);  // Subtract optimistically.
1386378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ Ret(vc);
1387378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ sub(right, left, Operand(right));  // Revert optimistic subtract.
1388378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      break;
1389378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    case Token::MUL:
1390378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Remove tag from one of the operands. This way the multiplication result
1391378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // will be a smi if it fits the smi range.
1392378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ SmiUntag(ip, right);
1393378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Do multiplication
1394378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // scratch1 = lower 32 bits of ip * left.
1395378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // scratch2 = higher 32 bits of ip * left.
1396378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ smull(scratch1, scratch2, left, ip);
1397378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Check for overflowing the smi range - no overflow if higher 33 bits of
1398378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // the result are identical.
1399378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ mov(ip, Operand(scratch1, ASR, 31));
1400378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ cmp(ip, Operand(scratch2));
1401378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ b(ne, &not_smi_result);
1402378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Go slow on zero result to handle -0.
140359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      __ cmp(scratch1, Operand::Zero());
1404378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ mov(right, Operand(scratch1), LeaveCC, ne);
1405378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ Ret(ne);
1406378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // We need -0 if we were multiplying a negative number with 0 to get 0.
1407378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // We know one of them was zero.
1408378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ add(scratch2, right, Operand(left), SetCC);
1409378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl);
1410378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ Ret(pl);  // Return smi 0 if the non-zero one was positive.
1411378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // We fall through here if we multiplied a negative number with 0, because
1412378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // that would mean we should produce -0.
1413378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      break;
1414a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case Token::DIV: {
1415a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      Label div_with_sdiv;
1416a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1417a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Check for 0 divisor.
141859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      __ cmp(right, Operand::Zero());
1419a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      __ b(eq, &not_smi_result);
1420a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
142131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      // Check for power of two on the right hand side.
1422a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      __ sub(scratch1, right, Operand(1));
1423a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      __ tst(scratch1, right);
1424a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      if (CpuFeatures::IsSupported(SUDIV)) {
1425a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &div_with_sdiv);
1426a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for no remainder.
1427a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ tst(left, scratch1);
1428a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &not_smi_result);
1429a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for positive left hand side.
143059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(left, Operand::Zero());
1431a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(mi, &div_with_sdiv);
1432a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      } else {
1433a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &not_smi_result);
1434a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for positive and no remainder.
1435a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ orr(scratch2, scratch1, Operand(0x80000000u));
1436a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ tst(left, scratch2);
1437a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &not_smi_result);
1438a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
143931b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
144031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      // Perform division by shifting.
1441b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org      __ clz(scratch1, scratch1);
144231b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      __ rsb(scratch1, scratch1, Operand(31));
144331b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      __ mov(right, Operand(left, LSR, scratch1));
144431b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      __ Ret();
1445a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1446a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      if (CpuFeatures::IsSupported(SUDIV)) {
1447837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org        CpuFeatureScope scope(masm, SUDIV);
1448a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        Label result_not_zero;
1449a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1450a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ bind(&div_with_sdiv);
1451a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Do division.
1452a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ sdiv(scratch1, left, right);
1453a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check that the remainder is zero.
1454a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ mls(scratch2, scratch1, right, left);
145559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(scratch2, Operand::Zero());
1456a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &not_smi_result);
1457a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for negative zero result.
145859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(scratch1, Operand::Zero());
1459a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &result_not_zero);
146059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(right, Operand::Zero());
1461a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(lt, &not_smi_result);
1462a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ bind(&result_not_zero);
1463a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for the corner case of dividing the most negative smi by -1.
1464a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ cmp(scratch1, Operand(0x40000000));
1465a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(eq, &not_smi_result);
1466a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Tag and return the result.
1467a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ SmiTag(right, scratch1);
1468a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ Ret();
1469a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
147031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      break;
1471a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
1472a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case Token::MOD: {
1473a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      Label modulo_with_sdiv;
1474a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1475a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      if (CpuFeatures::IsSupported(SUDIV)) {
1476a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for x % 0.
147759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(right, Operand::Zero());
1478a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(eq, &not_smi_result);
1479a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1480a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for two positive smis.
1481a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ orr(scratch1, left, Operand(right));
1482a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ tst(scratch1, Operand(0x80000000u));
1483a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &modulo_with_sdiv);
1484a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1485a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for power of two on the right hand side.
1486a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ sub(scratch1, right, Operand(1));
1487a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ tst(scratch1, right);
1488a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &modulo_with_sdiv);
1489a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      } else {
1490a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for two positive smis.
1491a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ orr(scratch1, left, Operand(right));
1492a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ tst(scratch1, Operand(0x80000000u));
1493a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ b(ne, &not_smi_result);
149431b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
1495a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Check for power of two on the right hand side.
1496a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ JumpIfNotPowerOfTwoOrZero(right, scratch1, &not_smi_result);
1497a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
149831b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
1499a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Perform modulus by masking (scratch1 contains right - 1).
150031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      __ and_(right, left, Operand(scratch1));
150131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      __ Ret();
1502a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
1503a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      if (CpuFeatures::IsSupported(SUDIV)) {
1504837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org        CpuFeatureScope scope(masm, SUDIV);
1505a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ bind(&modulo_with_sdiv);
1506a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ mov(scratch2, right);
1507a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Perform modulus with sdiv and mls.
1508a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ sdiv(scratch1, left, right);
1509a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ mls(right, scratch1, right, left);
1510a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // Return if the result is not 0.
151159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(right, Operand::Zero());
1512a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ Ret(ne);
1513a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // The result is 0, check for -0 case.
151459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(left, Operand::Zero());
1515a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ Ret(pl);
1516a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // This is a -0 case, restore the value of right.
1517a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        __ mov(right, scratch2);
1518a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        // We fall through here to not_smi_result to produce -0.
1519a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
152031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org      break;
1521a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
152283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::BIT_OR:
152383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ orr(right, left, Operand(right));
152483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ Ret();
152583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      break;
152683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::BIT_AND:
152783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ and_(right, left, Operand(right));
152883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ Ret();
152983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      break;
153083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::BIT_XOR:
153183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ eor(right, left, Operand(right));
153283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ Ret();
153383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      break;
1534496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::SAR:
1535496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Remove tags from right operand.
1536496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ GetLeastBitsFromSmi(scratch1, right, 5);
1537496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ mov(right, Operand(left, ASR, scratch1));
1538496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Smi tag result.
1539496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ bic(right, right, Operand(kSmiTagMask));
1540496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ Ret();
1541496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      break;
1542496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::SHR:
1543496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Remove tags from operands. We can't do this on a 31 bit number
1544496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // because then the 0s get shifted into bit 30 instead of bit 31.
1545496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ SmiUntag(scratch1, left);
1546496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ GetLeastBitsFromSmi(scratch2, right, 5);
1547496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ mov(scratch1, Operand(scratch1, LSR, scratch2));
1548496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Unsigned shift is not allowed to produce a negative number, so
1549496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // check the sign bit and the sign bit after Smi tagging.
1550496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ tst(scratch1, Operand(0xc0000000));
1551496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ b(ne, &not_smi_result);
1552496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Smi tag result.
1553496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ SmiTag(right, scratch1);
1554496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ Ret();
1555496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      break;
1556496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::SHL:
1557496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Remove tags from operands.
1558496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ SmiUntag(scratch1, left);
1559496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ GetLeastBitsFromSmi(scratch2, right, 5);
1560496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ mov(scratch1, Operand(scratch1, LSL, scratch2));
1561496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Check that the signed result fits in a Smi.
1562bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      __ TrySmiTag(right, scratch1, &not_smi_result);
1563496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      __ Ret();
1564496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      break;
1565378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    default:
1566378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      UNREACHABLE();
1567378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
1568378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ bind(&not_smi_result);
1569378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
1570378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1571378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1572fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
1573fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register result,
1574fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register heap_number_map,
1575fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register scratch1,
1576fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register scratch2,
1577fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Label* gc_required,
1578fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               OverwriteMode mode);
1579fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1580fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
1581fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
1582fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      BinaryOpIC::TypeInfo left_type,
1583fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      BinaryOpIC::TypeInfo right_type,
1584fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      bool smi_operands,
1585fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      Label* not_numbers,
1586fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      Label* gc_required,
1587fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      Label* miss,
1588fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      Token::Value op,
1589fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                      OverwriteMode mode) {
159031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  Register left = r1;
159131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  Register right = r0;
1592f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Register scratch1 = r6;
1593f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Register scratch2 = r7;
1594b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  Register scratch3 = r4;
159531b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
159683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  ASSERT(smi_operands || (not_numbers != NULL));
1597c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  if (smi_operands) {
1598c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    __ AssertSmi(left);
1599c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org    __ AssertSmi(right);
160083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  }
1601fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (left_type == BinaryOpIC::SMI) {
1602fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(left, miss);
1603fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
1604fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (right_type == BinaryOpIC::SMI) {
1605fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(right, miss);
1606fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
160731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
1608f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Register heap_number_map = r9;
160931b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
161031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
1611fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  switch (op) {
161283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::ADD:
161383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::SUB:
161483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::MUL:
161583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::DIV:
161683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::MOD: {
161783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // Allocate new heap number for result.
161883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      Register result = r5;
1619fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      BinaryOpStub_GenerateHeapResultAllocation(
1620fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org          masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
162183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
162232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      // Load left and right operands into d0 and d1.
162383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      if (smi_operands) {
1624bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org        __ SmiToDouble(d1, right);
1625bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org        __ SmiToDouble(d0, left);
162683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      } else {
162732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        // Load right operand into d1.
1628fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        if (right_type == BinaryOpIC::INT32) {
162932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          __ LoadNumberAsInt32Double(
163032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org              right, d1, heap_number_map, scratch1, d8, miss);
1631fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        } else {
16328432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org          Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
163332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          __ LoadNumber(right, d1, heap_number_map, scratch1, fail);
1634fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        }
163532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        // Load left operand into d0.
1636fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        if (left_type == BinaryOpIC::INT32) {
163732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          __ LoadNumberAsInt32Double(
163832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org              left, d0, heap_number_map, scratch1, d8, miss);
1639fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        } else {
16408432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org          Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
164132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          __ LoadNumber(
164232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org              left, d0, heap_number_map, scratch1, fail);
1643fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        }
164483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
164531b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
164683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // Calculate the result.
164732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      if (op != Token::MOD) {
164883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        // Using VFP registers:
164932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        // d0: Left value
165032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        // d1: Right value
1651fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        switch (op) {
165283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          case Token::ADD:
165332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vadd(d5, d0, d1);
165483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org            break;
165583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          case Token::SUB:
165632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vsub(d5, d0, d1);
165783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org            break;
165883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          case Token::MUL:
165932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vmul(d5, d0, d1);
166083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org            break;
166183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          case Token::DIV:
166232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vdiv(d5, d0, d1);
166383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org            break;
166483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          default:
166583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org            UNREACHABLE();
166683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        }
166731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
166883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        __ sub(r0, result, Operand(kHeapObjectTag));
166983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        __ vstr(d5, r0, HeapNumber::kValueOffset);
167083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        __ add(r0, r0, Operand(kHeapObjectTag));
167183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        __ Ret();
167283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      } else {
16739ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Call the C function to handle the double operation.
167432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        CallCCodeForDoubleOperation(masm, op, result, scratch1);
1675160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        if (FLAG_debug_code) {
1676160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org          __ stop("Unreachable code.");
1677160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        }
167883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
167983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      break;
168083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    }
168183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::BIT_OR:
168283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    case Token::BIT_XOR:
1683496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::BIT_AND:
1684496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::SAR:
1685496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::SHR:
1686496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    case Token::SHL: {
168783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      if (smi_operands) {
168883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        __ SmiUntag(r3, left);
168983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        __ SmiUntag(r2, right);
169083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      } else {
169183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        // Convert operands to 32-bit integers. Right in r2 and left in r3.
169232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        __ ConvertNumberToInt32(
169332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          left, r3, heap_number_map,
169432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          scratch1, scratch2, scratch3, d0, d1, not_numbers);
169532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        __ ConvertNumberToInt32(
169632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          right, r2, heap_number_map,
169732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          scratch1, scratch2, scratch3, d0, d1, not_numbers);
169883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
1699496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
1700496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      Label result_not_a_smi;
1701fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      switch (op) {
170283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        case Token::BIT_OR:
170383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          __ orr(r2, r3, Operand(r2));
170483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          break;
170583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        case Token::BIT_XOR:
170683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          __ eor(r2, r3, Operand(r2));
170783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          break;
170883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        case Token::BIT_AND:
170983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          __ and_(r2, r3, Operand(r2));
171083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          break;
1711496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org        case Token::SAR:
1712496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // Use only the 5 least significant bits of the shift count.
1713496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          __ GetLeastBitsFromInt32(r2, r2, 5);
1714496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          __ mov(r2, Operand(r3, ASR, r2));
1715496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          break;
1716496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org        case Token::SHR:
1717496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // Use only the 5 least significant bits of the shift count.
1718496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          __ GetLeastBitsFromInt32(r2, r2, 5);
1719496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          __ mov(r2, Operand(r3, LSR, r2), SetCC);
1720496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // SHR is special because it is required to produce a positive answer.
1721496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // The code below for writing into heap numbers isn't capable of
1722496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // writing the register as an unsigned int so we go to slow case if we
1723496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // hit this case.
1724e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org          __ b(mi, &result_not_a_smi);
1725496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          break;
1726496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org        case Token::SHL:
1727496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          // Use only the 5 least significant bits of the shift count.
1728496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          __ GetLeastBitsFromInt32(r2, r2, 5);
1729496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          __ mov(r2, Operand(r3, LSL, r2));
1730496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org          break;
173183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org        default:
173283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org          UNREACHABLE();
173383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
173483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
173583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // Check that the *signed* result fits in a smi.
1736bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      __ TrySmiTag(r0, r2, &result_not_a_smi);
173783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ Ret();
173883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
173983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // Allocate new heap number for result.
174083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ bind(&result_not_a_smi);
17413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      Register result = r5;
17423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (smi_operands) {
17433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        __ AllocateHeapNumber(
17443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org            result, scratch1, scratch2, heap_number_map, gc_required);
17453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } else {
1746fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        BinaryOpStub_GenerateHeapResultAllocation(
1747fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org            masm, result, heap_number_map, scratch1, scratch2, gc_required,
1748fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org            mode);
17493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      }
175083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
175183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // r2: Answer as signed int32.
175283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // r5: Heap number to write answer into.
175383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
175483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // Nothing can go wrong now, so move the heap number to r0, which is the
175583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      // result.
175683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      __ mov(r0, Operand(r5));
175783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
1758e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
1759e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // mentioned above SHR needs to always produce a positive result.
1760e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ vmov(s0, r2);
1761e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      if (op == Token::SHR) {
1762e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        __ vcvt_f64_u32(d0, s0);
176383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      } else {
1764e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        __ vcvt_f64_s32(d0, s0);
176583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
1766e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ sub(r3, r0, Operand(kHeapObjectTag));
1767e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ vstr(d0, r3, HeapNumber::kValueOffset);
1768e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ Ret();
176983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      break;
177083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    }
177183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org    default:
177283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      UNREACHABLE();
1773378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
1774378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
1775378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1776378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1777378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// Generate the smi code. If the operation on smis are successful this return is
1778378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// generated. If the result is not a smi and heap number allocation is not
1779378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// requested the code falls through. If number allocation is requested but a
1780fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org// heap number cannot be allocated the code jumps to the label gc_required.
1781fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateSmiCode(
178240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    MacroAssembler* masm,
1783160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    Label* use_runtime,
1784378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    Label* gc_required,
1785fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    Token::Value op,
1786fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
1787fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    OverwriteMode mode) {
1788378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Label not_smis;
1789378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1790378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register left = r1;
1791378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register right = r0;
1792378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register scratch1 = r7;
1793378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1794378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // Perform combined smi check on both operands.
1795378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ orr(scratch1, left, Operand(right));
17967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(scratch1, &not_smis);
1797378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
179831b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // If the smi-smi operation results in a smi return is generated.
1799fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  BinaryOpStub_GenerateSmiSmiOperation(masm, op);
1800378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1801378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // If heap number results are possible generate the result in an allocated
1802378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // heap number.
1803fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
1804fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    BinaryOpStub_GenerateFPOperation(
1805fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
1806fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        use_runtime, gc_required, &not_smis, op, mode);
1807378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
1808378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ bind(&not_smis);
1809378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
1810378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1811378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
181240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1813d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Label right_arg_changed, call_runtime;
1814d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
18151510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  if (op_ == Token::MOD && encoded_right_arg_.has_value) {
1816d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // It is guaranteed that the value will fit into a Smi, because if it
1817d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // didn't, we wouldn't be here, see BinaryOp_Patch.
1818d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value())));
1819d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ b(ne, &right_arg_changed);
1820d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
1821378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
182240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (result_type_ == BinaryOpIC::UNINITIALIZED ||
182340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      result_type_ == BinaryOpIC::SMI) {
1824378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // Only allow smi results.
1825fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    BinaryOpStub_GenerateSmiCode(
1826fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_);
1827378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  } else {
1828378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // Allow heap number result and don't make a transition if a heap number
1829378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // cannot be allocated.
1830fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    BinaryOpStub_GenerateSmiCode(
1831fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS,
1832fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        mode_);
1833378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
1834378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1835378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // Code falls through if the result is not returned as either a smi or heap
1836378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // number.
1837d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&right_arg_changed);
1838378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  GenerateTypeTransition(masm);
1839378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1840378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ bind(&call_runtime);
18414e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  {
18424e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
18434e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateRegisterArgsPush(masm);
18444e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateCallRuntime(masm);
18454e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
18464e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ Ret();
1847378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
1848378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
1849378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
185040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
1851160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Label call_runtime;
1852fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING);
1853160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  ASSERT(op_ == Token::ADD);
1854160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // If both arguments are strings, call the string add stub.
1855160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Otherwise, do a transition.
1856160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1857160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Registers containing left and right operands respectively.
1858160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Register left = r1;
1859160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Register right = r0;
1860160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1861160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Test if left operand is a string.
1862160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ JumpIfSmi(left, &call_runtime);
1863160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
1864160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ b(ge, &call_runtime);
1865160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1866160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // Test if right operand is a string.
1867160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ JumpIfSmi(right, &call_runtime);
1868160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
1869160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ b(ge, &call_runtime);
1870160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1871ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  StringAddStub string_add_stub(
1872ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME));
1873160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  GenerateRegisterArgsPush(masm);
1874160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ TailCallStub(&string_add_stub);
1875160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1876160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ bind(&call_runtime);
1877160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  GenerateTypeTransition(masm);
1878160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org}
1879160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
1880160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
188140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
1882fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32);
1883378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
18849ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Register left = r1;
18859ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Register right = r0;
18869ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Register scratch1 = r7;
18879ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Register scratch2 = r9;
1888fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  LowDwVfpRegister double_scratch = d0;
18899ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
18909ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Register heap_number_result = no_reg;
18919ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Register heap_number_map = r6;
18929ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
18939ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
18949ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Label call_runtime;
18959ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Labels for type transition, used for wrong input or output types.
18969ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Both label are currently actually bound to the same position. We use two
18979ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // different label to differentiate the cause leading to type transition.
18989ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Label transition;
18999ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
19009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Smi-smi fast case.
19019ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  Label skip;
19029ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  __ orr(scratch1, left, right);
19039ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  __ JumpIfNotSmi(scratch1, &skip);
1904fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  BinaryOpStub_GenerateSmiSmiOperation(masm, op_);
19059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Fall through if the result is not a smi.
19069ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  __ bind(&skip);
19079ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
19089ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  switch (op_) {
19099ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::ADD:
19109ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::SUB:
19119ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::MUL:
19129ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::DIV:
19139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::MOD: {
1914fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // It could be that only SMIs have been seen at either the left
1915fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // or the right operand. For precise type feedback, patch the IC
1916fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // again if this changes.
1917fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      if (left_type_ == BinaryOpIC::SMI) {
1918fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ JumpIfNotSmi(left, &transition);
1919fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      }
1920fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      if (right_type_ == BinaryOpIC::SMI) {
1921fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        __ JumpIfNotSmi(right, &transition);
1922fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      }
19237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      // Load both operands and check that they are 32-bit integer.
19247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      // Jump to type transition if they are not. The registers r0 and r1 (right
19257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      // and left) are preserved for the runtime call.
192632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ LoadNumberAsInt32Double(
192732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        right, d1, heap_number_map, scratch1, d8, &transition);
192832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ LoadNumberAsInt32Double(
192932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        left, d0, heap_number_map, scratch1, d8, &transition);
193032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org
193132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      if (op_ != Token::MOD) {
19329ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        Label return_heap_number;
19339ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        switch (op_) {
19349ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          case Token::ADD:
193532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vadd(d5, d0, d1);
19369ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org            break;
19379ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          case Token::SUB:
193832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vsub(d5, d0, d1);
19399ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org            break;
19409ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          case Token::MUL:
194132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vmul(d5, d0, d1);
19429ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org            break;
19439ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          case Token::DIV:
194432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org            __ vdiv(d5, d0, d1);
19459ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org            break;
19469ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          default:
19479ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org            UNREACHABLE();
19489ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        }
19499ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
1950837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org        if (result_type_ <= BinaryOpIC::INT32) {
1951837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          __ TryDoubleToInt32Exact(scratch1, d5, d8);
1952837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          // If the ne condition is set, result does
1953837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          // not fit in a 32-bit integer.
1954837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          __ b(ne, &transition);
1955837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          // Try to tag the result as a Smi, return heap number on overflow.
1956837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          __ SmiTag(scratch1, SetCC);
1957837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          __ b(vs, &return_heap_number);
1958837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          // Check for minus zero, transition in that case (because we need
1959837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          // to return a heap number).
19607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          Label not_zero;
1961837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          ASSERT(kSmiTag == 0);
19627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          __ b(ne, &not_zero);
1963fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          __ VmovHigh(scratch2, d5);
19647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          __ tst(scratch2, Operand(HeapNumber::kSignMask));
1965837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          __ b(ne, &transition);
19667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          __ bind(&not_zero);
1967837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org          __ mov(r0, scratch1);
19689ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ Ret();
19699ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        }
19709ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
1971d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com        __ bind(&return_heap_number);
1972d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com        // Return a heap number, or fall through to type transition or runtime
1973d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com        // call if we can't.
197432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        // We are using vfp registers so r5 is available.
197532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        heap_number_result = r5;
197632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        BinaryOpStub_GenerateHeapResultAllocation(masm,
197732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                                  heap_number_result,
197832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                                  heap_number_map,
197932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                                  scratch1,
198032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                                  scratch2,
198132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                                  &call_runtime,
198232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                                  mode_);
198332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
198432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        __ vstr(d5, r0, HeapNumber::kValueOffset);
198532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        __ mov(r0, heap_number_result);
198632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        __ Ret();
19879ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
19889ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // A DIV operation expecting an integer result falls through
19899ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // to type transition.
19909ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
19919ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      } else {
19921510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        if (encoded_right_arg_.has_value) {
1993d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org          __ Vmov(d8, fixed_right_arg_value(), scratch1);
1994d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org          __ VFPCompareAndSetFlags(d1, d8);
1995d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org          __ b(ne, &transition);
1996d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org        }
1997d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
19989ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // We preserved r0 and r1 to be able to call runtime.
19999ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Save the left value on the stack.
20009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        __ Push(r5, r4);
20019ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20023847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com        Label pop_and_call_runtime;
20033847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com
20049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Allocate a heap number to store the result.
20059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        heap_number_result = r5;
2006fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        BinaryOpStub_GenerateHeapResultAllocation(masm,
2007fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                  heap_number_result,
2008fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                  heap_number_map,
2009fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                  scratch1,
2010fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                  scratch2,
2011fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                  &pop_and_call_runtime,
2012fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                  mode_);
20139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20149ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Load the left value from the value saved on the stack.
20159ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        __ Pop(r1, r0);
20169ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20179ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Call the C function to handle the double operation.
201832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
2019160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        if (FLAG_debug_code) {
2020160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org          __ stop("Unreachable code.");
2021160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        }
20223847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com
20233847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com        __ bind(&pop_and_call_runtime);
20243847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com        __ Drop(2);
20253847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com        __ b(&call_runtime);
20269ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      }
20279ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20289ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      break;
20299ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    }
20309ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20319ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::BIT_OR:
20329ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::BIT_XOR:
20339ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::BIT_AND:
20349ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::SAR:
20359ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::SHR:
20369ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::SHL: {
20379ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      Label return_heap_number;
20389ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      // Convert operands to 32-bit integers. Right in r2 and left in r3. The
20399ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      // registers r0 and r1 (right and left) are preserved for the runtime
20409ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      // call.
204132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ LoadNumberAsInt32(left, r3, heap_number_map,
204232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                           scratch1, d0, d1, &transition);
204332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ LoadNumberAsInt32(right, r2, heap_number_map,
204432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                           scratch1, d0, d1, &transition);
20459ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20469ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      // The ECMA-262 standard specifies that, for shift operations, only the
20479ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      // 5 least significant bits of the shift value should be used.
20489ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      switch (op_) {
20499ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        case Token::BIT_OR:
20509ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ orr(r2, r3, Operand(r2));
20519ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          break;
20529ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        case Token::BIT_XOR:
20539ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ eor(r2, r3, Operand(r2));
20549ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          break;
20559ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        case Token::BIT_AND:
20569ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ and_(r2, r3, Operand(r2));
20579ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          break;
20589ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        case Token::SAR:
20599ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ and_(r2, r2, Operand(0x1f));
20609ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ mov(r2, Operand(r3, ASR, r2));
20619ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          break;
20629ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        case Token::SHR:
20639ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ and_(r2, r2, Operand(0x1f));
20649ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ mov(r2, Operand(r3, LSR, r2), SetCC);
20659ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          // SHR is special because it is required to produce a positive answer.
20669ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          // We only get a negative result if the shift value (r2) is 0.
20679ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          // This result cannot be respresented as a signed 32-bit integer, try
20689ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          // to return a heap number if we can.
2069e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org          __ b(mi, (result_type_ <= BinaryOpIC::INT32)
2070e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org               ? &transition
2071e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org               : &return_heap_number);
20729ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          break;
20739ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        case Token::SHL:
20749ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ and_(r2, r2, Operand(0x1f));
20759ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ mov(r2, Operand(r3, LSL, r2));
20769ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          break;
20779ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        default:
20789ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          UNREACHABLE();
20799ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      }
20809ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
2081bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      // Check if the result fits in a smi. If not try to return a heap number.
2082bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      // (We know the result is an int32).
2083bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org      __ TrySmiTag(r0, r2, &return_heap_number);
20849ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      __ Ret();
20859ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
20869ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      __ bind(&return_heap_number);
2087160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org      heap_number_result = r5;
2088fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      BinaryOpStub_GenerateHeapResultAllocation(masm,
2089fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                heap_number_result,
2090fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                heap_number_map,
2091fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                scratch1,
2092fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                scratch2,
2093fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                &call_runtime,
2094fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                                mode_);
2095160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
2096e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      if (op_ != Token::SHR) {
2097e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        // Convert the result to a floating point value.
2098e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        __ vmov(double_scratch.low(), r2);
2099e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        __ vcvt_f64_s32(double_scratch, double_scratch.low());
21009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      } else {
2101e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        // The result must be interpreted as an unsigned 32-bit integer.
2102e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        __ vmov(double_scratch.low(), r2);
2103e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        __ vcvt_f64_u32(double_scratch, double_scratch.low());
21049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      }
21059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
2106e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // Store the result.
2107e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
2108e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ vstr(double_scratch, r0, HeapNumber::kValueOffset);
2109e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ mov(r0, heap_number_result);
2110e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      __ Ret();
2111e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
21129ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      break;
21139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    }
21149ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
21159ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    default:
21169ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      UNREACHABLE();
21179ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  }
21189ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
2119d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // We never expect DIV to yield an integer result, so we always generate
2120d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // type transition code for DIV operations expecting an integer result: the
2121d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  // code will fall through to this type transition.
2122d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  if (transition.is_linked() ||
2123d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com      ((op_ == Token::DIV) && (result_type_ <= BinaryOpIC::INT32))) {
21249ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    __ bind(&transition);
21259ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    GenerateTypeTransition(masm);
21269ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  }
21279ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
21289ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  __ bind(&call_runtime);
21294e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  {
21304e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
21314e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateRegisterArgsPush(masm);
21324e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateCallRuntime(masm);
21334e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
21344e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ Ret();
2135378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
2136378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2137378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
213840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
2139b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org  Label call_runtime;
2140378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
21417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (op_ == Token::ADD) {
21427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // Handle string addition here, because it is the only operation
21437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    // that does not do a ToNumber conversion on the operands.
21447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    GenerateAddStrings(masm);
21457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
21467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Convert oddball arguments to numbers.
21487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Label check, done;
21497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ CompareRoot(r1, Heap::kUndefinedValueRootIndex);
21507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ b(ne, &check);
21517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (Token::IsBitOp(op_)) {
21527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    __ mov(r1, Operand(Smi::FromInt(0)));
21537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {
21547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    __ LoadRoot(r1, Heap::kNanValueRootIndex);
21557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
21567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ jmp(&done);
21577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ bind(&check);
21587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
21597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ b(ne, &done);
21607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  if (Token::IsBitOp(op_)) {
21617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    __ mov(r0, Operand(Smi::FromInt(0)));
21627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  } else {
21637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    __ LoadRoot(r0, Heap::kNanValueRootIndex);
21647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  }
21657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ bind(&done);
21667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21678432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  GenerateNumberStub(masm);
21687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
21697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
21718432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
2172fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label call_runtime, transition;
2173fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  BinaryOpStub_GenerateFPOperation(
2174fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      masm, left_type_, right_type_, false,
2175fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      &transition, &call_runtime, &transition, op_, mode_);
2176fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2177fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&transition);
2178fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  GenerateTypeTransition(masm);
2179378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2180378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ bind(&call_runtime);
21814e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  {
21824e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
21834e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateRegisterArgsPush(masm);
21844e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateCallRuntime(masm);
21854e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
21864e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ Ret();
2187378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
2188378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2189378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
219040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
2191fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label call_runtime, call_string_add_or_runtime, transition;
2192378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2193fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  BinaryOpStub_GenerateSmiCode(
2194fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_);
2195378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2196fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  BinaryOpStub_GenerateFPOperation(
2197fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      masm, left_type_, right_type_, false,
2198fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      &call_string_add_or_runtime, &call_runtime, &transition, op_, mode_);
2199fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2200fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&transition);
2201fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  GenerateTypeTransition(masm);
2202378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
22033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ bind(&call_string_add_or_runtime);
2204378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  if (op_ == Token::ADD) {
2205378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    GenerateAddStrings(masm);
2206378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
2207378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
22083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ bind(&call_runtime);
22094e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  {
22104e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
22114e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateRegisterArgsPush(masm);
22124e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateCallRuntime(masm);
22134e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
22144e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ Ret();
2215378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
2216378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2217378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
221840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
2219378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  ASSERT(op_ == Token::ADD);
22203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  Label left_not_string, call_runtime;
2221378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2222378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register left = r1;
2223378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  Register right = r0;
2224378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
22253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Check if left argument is a string.
22263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ JumpIfSmi(left, &left_not_string);
2227378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
22283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ b(ge, &left_not_string);
2229378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2230ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  StringAddStub string_add_left_stub(
2231ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      (StringAddFlags)(STRING_ADD_CHECK_RIGHT | STRING_ADD_ERECT_FRAME));
22323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  GenerateRegisterArgsPush(masm);
22333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ TailCallStub(&string_add_left_stub);
22343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
22353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Left operand is not a string, test right.
22363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ bind(&left_not_string);
2237378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfSmi(right, &call_runtime);
2238378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
2239378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ b(ge, &call_runtime);
2240378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2241ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  StringAddStub string_add_right_stub(
2242ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME));
2243378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  GenerateRegisterArgsPush(masm);
22443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ TailCallStub(&string_add_right_stub);
2245378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2246378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // At least one argument is not a string.
2247378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ bind(&call_runtime);
2248378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
2249378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2250378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2251fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
2252fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register result,
2253fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register heap_number_map,
2254fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register scratch1,
2255fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Register scratch2,
2256fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               Label* gc_required,
2257fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                                               OverwriteMode mode) {
2258378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // Code below will scratch result if allocation fails. To keep both arguments
2259378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  // intact for the runtime call result cannot be one of these.
2260378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  ASSERT(!result.is(r0) && !result.is(r1));
2261378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2262fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (mode == OVERWRITE_LEFT || mode == OVERWRITE_RIGHT) {
2263378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    Label skip_allocation, allocated;
2264fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    Register overwritable_operand = mode == OVERWRITE_LEFT ? r1 : r0;
2265378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // If the overwritable operand is already an object, we skip the
2266378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // allocation of a heap number.
2267378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ JumpIfNotSmi(overwritable_operand, &skip_allocation);
2268378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // Allocate a heap number for the result.
2269378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ AllocateHeapNumber(
2270378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        result, scratch1, scratch2, heap_number_map, gc_required);
2271378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ b(&allocated);
2272378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ bind(&skip_allocation);
2273378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    // Use object holding the overwritable operand for result.
2274378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ mov(result, Operand(overwritable_operand));
2275378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ bind(&allocated);
2276378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  } else {
2277fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    ASSERT(mode == NO_OVERWRITE);
2278378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org    __ AllocateHeapNumber(
2279378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org        result, scratch1, scratch2, heap_number_map, gc_required);
2280378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  }
2281378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org}
2282378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
2283378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
228440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
2285378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ Push(r1, r0);
2286a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
2287a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2288a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
228965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid TranscendentalCacheStub::Generate(MacroAssembler* masm) {
22908f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // Untagged case: double input in d2, double result goes
22918f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  //   into d2.
22928f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  // Tagged case: tagged input on top of stack and in r0,
22938f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  //   tagged result (heap number) goes into r0.
22948f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
229565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label input_not_smi;
229665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label loaded;
22978f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  Label calculate;
22988f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  Label invalid_cache;
22998f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  const Register scratch0 = r9;
23008f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  const Register scratch1 = r7;
23018f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  const Register cache_entry = r0;
23028f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  const bool tagged = (argument_type_ == TAGGED);
230365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2304e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (tagged) {
2305e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Argument is a number and is on stack and in r0.
2306e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Load argument and check if it is a smi.
2307e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ JumpIfNotSmi(r0, &input_not_smi);
2308e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2309e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Input is a smi. Convert to double and load the low and high words
2310e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // of the double into r2, r3.
2311bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiToDouble(d7, r0);
2312bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ vmov(r2, r3, d7);
2313e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ b(&loaded);
2314e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2315e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ bind(&input_not_smi);
2316e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Check if input is a HeapNumber.
2317e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ CheckMap(r0,
2318e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                r1,
2319e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                Heap::kHeapNumberMapRootIndex,
2320e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                &calculate,
2321e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                DONT_DO_SMI_CHECK);
2322e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Input is a HeapNumber. Load it to a double register and store the
2323e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // low and high words into r2, r3.
2324e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
2325e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vmov(r2, r3, d0);
2326e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  } else {
2327e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Input is untagged double in d2. Output goes to d2.
2328e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vmov(r2, r3, d2);
2329e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
2330e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&loaded);
2331e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // r2 = low 32 bits of double value
2332e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // r3 = high 32 bits of double value
2333e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Compute hash (the shifts are arithmetic):
2334e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
2335e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ eor(r1, r2, Operand(r3));
2336e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ eor(r1, r1, Operand(r1, ASR, 16));
2337e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ eor(r1, r1, Operand(r1, ASR, 8));
2338e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
2339e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ And(r1, r1, Operand(TranscendentalCache::SubCache::kCacheSize - 1));
2340e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2341e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // r2 = low 32 bits of double value.
2342e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // r3 = high 32 bits of double value.
2343e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // r1 = TranscendentalCache::hash(double value).
2344e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Isolate* isolate = masm->isolate();
2345e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ExternalReference cache_array =
2346e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      ExternalReference::transcendental_cache_array_address(isolate);
2347e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(cache_entry, Operand(cache_array));
2348e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // cache_entry points to cache array.
2349e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int cache_array_index
2350e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      = type_ * sizeof(isolate->transcendental_cache()->caches_[0]);
2351e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ ldr(cache_entry, MemOperand(cache_entry, cache_array_index));
2352e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // r0 points to the cache for the type type_.
2353e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // If NULL, the cache hasn't been initialized yet, so go through runtime.
2354e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ cmp(cache_entry, Operand::Zero());
2355e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ b(eq, &invalid_cache);
235665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
235765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef DEBUG
2358e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Check that the layout of cache elements match expectations.
2359e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  { TranscendentalCache::SubCache::Element test_elem[2];
2360e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
2361e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
2362e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
2363e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
2364e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
2365e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    CHECK_EQ(12, elem2_start - elem_start);  // Two uint_32's and a pointer.
2366e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    CHECK_EQ(0, elem_in0 - elem_start);
2367e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    CHECK_EQ(kIntSize, elem_in1 - elem_start);
2368e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    CHECK_EQ(2 * kIntSize, elem_out - elem_start);
2369e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
237065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif
237165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2372e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12].
2373e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ add(r1, r1, Operand(r1, LSL, 1));
2374e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ add(cache_entry, cache_entry, Operand(r1, LSL, 2));
2375e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Check if cache matches: Double value is stored in uint32_t[2] array.
2376e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ ldm(ia, cache_entry, r4.bit() | r5.bit() | r6.bit());
2377e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ cmp(r2, r4);
2378e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ cmp(r3, r5, eq);
2379e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ b(ne, &calculate);
2380e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Cache hit. Load result, cleanup and return.
2381e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Counters* counters = masm->isolate()->counters();
2382e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ IncrementCounter(
2383e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      counters->transcendental_cache_hit(), 1, scratch0, scratch1);
2384e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (tagged) {
2385e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Pop input value from stack and load result into r0.
2386e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ pop();
2387e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ mov(r0, Operand(r6));
2388e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  } else {
2389e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Load result into d2.
2390e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
2391e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
2392e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Ret();
23938f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
23948f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  __ bind(&calculate);
23951b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ IncrementCounter(
23961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      counters->transcendental_cache_miss(), 1, scratch0, scratch1);
23978f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  if (tagged) {
23988f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ bind(&invalid_cache);
2399ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ExternalReference runtime_function =
2400ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        ExternalReference(RuntimeFunction(), masm->isolate());
2401ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    __ TailCallExternalReference(runtime_function, 1, 1);
24028f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  } else {
24038f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    Label no_update;
24048f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    Label skip_cache;
24058f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
24068f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // Call C function to calculate the result and update the cache.
240728583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    // r0: precalculated cache entry address.
240828583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    // r2 and r3: parts of the double value.
240928583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    // Store r0, r2 and r3 on stack for later before calling C function.
241028583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    __ Push(r3, r2, cache_entry);
24118f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    GenerateCallCFunction(masm, scratch0);
24128f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ GetCFunctionDoubleResult(d2);
24138f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
24148f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // Try to update the cache. If we cannot allocate a
24158f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // heap number, we return the result without updating.
241628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    __ Pop(r3, r2, cache_entry);
24178f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
24188f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ AllocateHeapNumber(r6, scratch0, scratch1, r5, &no_update);
24198f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ vstr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
24208f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ stm(ia, cache_entry, r2.bit() | r3.bit() | r6.bit());
24218f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ Ret();
24228f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
24238f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ bind(&invalid_cache);
24248f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // The cache is invalid. Call runtime which will recreate the
24258f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // cache.
24268f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
24278f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ AllocateHeapNumber(r0, scratch0, scratch1, r5, &skip_cache);
24288f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ vstr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
2429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
2430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
2431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(r0);
2432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallRuntime(RuntimeFunction(), 1);
2433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
24348f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ vldr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
24358f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ Ret();
24368f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
24378f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ bind(&skip_cache);
24388f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // Call C function to calculate the result and answer directly
24398f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // without updating the cache.
24408f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    GenerateCallCFunction(masm, scratch0);
24418f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ GetCFunctionDoubleResult(d2);
24428f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ bind(&no_update);
24438f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
24448f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // We return the value in d2 without adding it to the cache, but
24458f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    // we cause a scavenging GC so that future allocations will succeed.
2446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
2447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
2448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Allocate an aligned object larger than a HeapNumber.
2450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(4 * kPointerSize >= HeapNumber::kSize);
2451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ mov(scratch0, Operand(4 * kPointerSize));
2452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(scratch0);
2453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
2454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
245565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Ret();
245665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
24578f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org}
24588f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org
245965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
24608f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.orgvoid TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
24618f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org                                                    Register scratch) {
2462ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = masm->isolate();
2463ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
24648f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  __ push(lr);
24658e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  __ PrepareCallCFunction(0, 1, scratch);
24668e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  if (masm->use_eabi_hardfloat()) {
24678e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    __ vmov(d0, d2);
24688e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  } else {
24698e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    __ vmov(r0, r1, d2);
24708e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  }
2471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  AllowExternalCallThatCantCauseGC scope(masm);
24728f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  switch (type_) {
24738f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    case TranscendentalCache::SIN:
24748e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      __ CallCFunction(ExternalReference::math_sin_double_function(isolate),
24758e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org          0, 1);
24768f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org      break;
24778f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    case TranscendentalCache::COS:
24788e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      __ CallCFunction(ExternalReference::math_cos_double_function(isolate),
24798e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org          0, 1);
24808f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org      break;
24811b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    case TranscendentalCache::TAN:
24821b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      __ CallCFunction(ExternalReference::math_tan_double_function(isolate),
24831b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          0, 1);
24841b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      break;
24858f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    case TranscendentalCache::LOG:
24868e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      __ CallCFunction(ExternalReference::math_log_double_function(isolate),
24878e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org          0, 1);
24888f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org      break;
24898f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    default:
24908f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org      UNIMPLEMENTED();
24918f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org      break;
24928f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  }
24938f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org  __ pop(lr);
249465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
249565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
249665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
249765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgRuntime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
249865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  switch (type_) {
249965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Add more cases when necessary.
250065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    case TranscendentalCache::SIN: return Runtime::kMath_sin;
250165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    case TranscendentalCache::COS: return Runtime::kMath_cos;
25021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    case TranscendentalCache::TAN: return Runtime::kMath_tan;
2503a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case TranscendentalCache::LOG: return Runtime::kMath_log;
250465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    default:
250565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      UNIMPLEMENTED();
250665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      return Runtime::kAbort;
250765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
250865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
250965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
251065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
251165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StackCheckStub::Generate(MacroAssembler* masm) {
25124a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
251365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
251465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
251565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
251656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvoid InterruptStub::Generate(MacroAssembler* masm) {
251756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  __ TailCallRuntime(Runtime::kInterrupt, 0, 1);
251856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org}
251956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
252056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org
25214d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.orgvoid MathPowStub::Generate(MacroAssembler* masm) {
252264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register base = r1;
252364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register exponent = r2;
252464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register heapnumbermap = r5;
252564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register heapnumber = r0;
2526a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  const DwVfpRegister double_base = d1;
2527a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  const DwVfpRegister double_exponent = d2;
2528a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  const DwVfpRegister double_result = d3;
2529a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  const DwVfpRegister double_scratch = d0;
253064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const SwVfpRegister single_scratch = s0;
253164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register scratch = r9;
253264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register scratch2 = r7;
253364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
2534fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Label call_runtime, done, int_exponent;
253564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (exponent_type_ == ON_STACK) {
253664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    Label base_is_smi, unpack_exponent;
253764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // The exponent and base are supplied as arguments on the stack.
253864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // This can only happen if the stub is called from non-optimized code.
253964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Load input parameters from stack to double registers.
25404d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ ldr(base, MemOperand(sp, 1 * kPointerSize));
25414d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ ldr(exponent, MemOperand(sp, 0 * kPointerSize));
25424d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
254364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
25444d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
2545fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ UntagAndJumpIfSmi(scratch, base, &base_is_smi);
25464d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset));
25474d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ cmp(scratch, heapnumbermap);
25484d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ b(ne, &call_runtime);
254964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
25504d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
255164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&unpack_exponent);
255264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
255364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&base_is_smi);
2554fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ vmov(single_scratch, scratch);
255564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ vcvt_f64_s32(double_base, single_scratch);
255664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&unpack_exponent);
25574d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
2558fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
25594d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
25604d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
25614d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ cmp(scratch, heapnumbermap);
25624d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ b(ne, &call_runtime);
25634d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ vldr(double_exponent,
25644d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org            FieldMemOperand(exponent, HeapNumber::kValueOffset));
256564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else if (exponent_type_ == TAGGED) {
256664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Base is already in double_base.
2567fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
256864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
256964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ vldr(double_exponent,
257064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            FieldMemOperand(exponent, HeapNumber::kValueOffset));
257164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
257264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
257364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (exponent_type_ != INTEGER) {
257464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    Label int_exponent_convert;
257564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Detect integer exponents stored as double.
257664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ vcvt_u32_f64(single_scratch, double_exponent);
257764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // We do not check for NaN or Infinity here because comparing numbers on
257864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // ARM correctly distinguishes NaNs.  We end up calling the built-in.
257964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ vcvt_f64_u32(double_scratch, single_scratch);
258064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ VFPCompareAndSetFlags(double_scratch, double_exponent);
258164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ b(eq, &int_exponent_convert);
258264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
258364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    if (exponent_type_ == ON_STACK) {
258464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Detect square root case.  Crankshaft detects constant +/-0.5 at
258564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // compile time and uses DoMathPowHalf instead.  We then skip this check
258664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // for non-constant cases of +/-0.5 as these hardly occur.
258764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      Label not_plus_half;
258864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
258964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Test for 0.5.
259033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      __ vmov(double_scratch, 0.5, scratch);
259164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ VFPCompareAndSetFlags(double_exponent, double_scratch);
259264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ b(ne, &not_plus_half);
259364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
259464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Calculates square root of base.  Check for the special case of
259564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
259633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      __ vmov(double_scratch, -V8_INFINITY, scratch);
259764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ VFPCompareAndSetFlags(double_base, double_scratch);
259864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vneg(double_result, double_scratch, eq);
259964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ b(eq, &done);
260064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
260164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Add +0 to convert -0 to +0.
260264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vadd(double_scratch, double_base, kDoubleRegZero);
260364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vsqrt(double_result, double_scratch);
260464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ jmp(&done);
260564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
260664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ bind(&not_plus_half);
260733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      __ vmov(double_scratch, -0.5, scratch);
260864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ VFPCompareAndSetFlags(double_exponent, double_scratch);
260964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ b(ne, &call_runtime);
261064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
261164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Calculates square root of base.  Check for the special case of
261264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
261333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      __ vmov(double_scratch, -V8_INFINITY, scratch);
261464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ VFPCompareAndSetFlags(double_base, double_scratch);
261564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vmov(double_result, kDoubleRegZero, eq);
261664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ b(eq, &done);
261764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
261864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Add +0 to convert -0 to +0.
261964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vadd(double_scratch, double_base, kDoubleRegZero);
262033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      __ vmov(double_result, 1.0, scratch);
262164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vsqrt(double_scratch, double_scratch);
262264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ vdiv(double_result, double_result, double_scratch);
262364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ jmp(&done);
262464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    }
26254d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
26264d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ push(lr);
2627c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
2628c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      AllowExternalCallThatCantCauseGC scope(masm);
262964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ PrepareCallCFunction(0, 2, scratch);
263064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ SetCallCDoubleArguments(double_base, double_exponent);
2631c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallCFunction(
2632c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          ExternalReference::power_double_double_function(masm->isolate()),
2633c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          0, 2);
2634c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
263564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(lr);
263664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ GetCFunctionDoubleResult(double_result);
263764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&done);
263864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
263964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&int_exponent_convert);
264064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ vcvt_u32_f64(single_scratch, double_exponent);
2641fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ vmov(scratch, single_scratch);
264264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
264364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
264464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Calculate power with integer exponent.
264564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&int_exponent);
264664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
2647fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Get two copies of exponent in the registers scratch and exponent.
2648fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  if (exponent_type_ == INTEGER) {
2649fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ mov(scratch, exponent);
2650fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  } else {
2651fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    // Exponent has previously been stored into scratch as untagged integer.
2652fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ mov(exponent, scratch);
2653fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  }
265464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ vmov(double_scratch, double_base);  // Back up base.
265533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ vmov(double_result, 1.0, scratch2);
265664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
265764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Get absolute value of exponent.
265859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(scratch, Operand::Zero());
265959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(scratch2, Operand::Zero(), LeaveCC, mi);
266064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ sub(scratch, scratch2, scratch, LeaveCC, mi);
266164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
266264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label while_true;
266364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&while_true);
266464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(scratch, Operand(scratch, ASR, 1), SetCC);
266564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ vmul(double_result, double_result, double_scratch, cs);
266664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ vmul(double_scratch, double_scratch, double_scratch, ne);
266764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ b(ne, &while_true);
266864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
266959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(exponent, Operand::Zero());
267064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ b(ge, &done);
267133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ vmov(double_scratch, 1.0, scratch);
267264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ vdiv(double_result, double_scratch, double_result);
267364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Test whether result is zero.  Bail out to check for subnormal result.
267464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
267564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ VFPCompareAndSetFlags(double_result, 0.0);
267664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ b(ne, &done);
267764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // double_exponent may not containe the exponent value if the input was a
267864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // smi.  We set it with exponent value before bailing out.
267964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ vmov(single_scratch, exponent);
268064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ vcvt_f64_s32(double_exponent, single_scratch);
268164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
268264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Returning or bailing out.
268364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Counters* counters = masm->isolate()->counters();
268464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (exponent_type_ == ON_STACK) {
268564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // The arguments are still on the stack.
268664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&call_runtime);
268764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
268864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
268964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // The stub is called from non-optimized code, which expects the result
269064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // as heap number in exponent.
269164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&done);
269264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ AllocateHeapNumber(
269364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        heapnumber, scratch, scratch2, heapnumbermap, &call_runtime);
26944d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    __ vstr(double_result,
26954d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org            FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
269664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    ASSERT(heapnumber.is(r0));
269764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
269864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ Ret(2);
269964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else {
270064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ push(lr);
270164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    {
270264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      AllowExternalCallThatCantCauseGC scope(masm);
270364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ PrepareCallCFunction(0, 2, scratch);
270464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ SetCallCDoubleArguments(double_base, double_exponent);
270564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ CallCFunction(
270664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          ExternalReference::power_double_double_function(masm->isolate()),
270764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          0, 2);
270864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    }
270964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(lr);
271064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ GetCFunctionDoubleResult(double_result);
27114d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
271264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&done);
271364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
271464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ Ret();
271564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
27164d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org}
27174d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
27184d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
27194d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.orgbool CEntryStub::NeedsImmovableCode() {
27204d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org  return true;
27214d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org}
27224d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
27234d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
2724c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool CEntryStub::IsPregenerated() {
2725c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
2726c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          result_size_ == 1;
2727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2729c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
27308432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
27318432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  CEntryStub::GenerateAheadOfTime(isolate);
27328432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate);
27338432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2734e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
27358432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
27361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2737bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2739c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2740c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
27418432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CodeStub::GenerateFPStubs(Isolate* isolate) {
2742e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  SaveFPRegsMode mode = kSaveFPRegs;
2743a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CEntryStub save_doubles(1, mode);
2744a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  StoreBufferOverflowStub stub(mode);
2745a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // These stubs might already be in the snapshot, detect that and don't
2746a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // regenerate, which would lead to code stub initialization state being messed
2747a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // up.
2748750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  Code* save_doubles_code;
2749750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
2750750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    save_doubles_code = *save_doubles.GetCode(isolate);
2751a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
2752e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Code* store_buffer_overflow_code;
2753e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (!stub.FindCodeInCache(&store_buffer_overflow_code, isolate)) {
2754e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      store_buffer_overflow_code = *stub.GetCode(isolate);
2755e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
2756e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  save_doubles_code->set_is_pregenerated(true);
2757e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  store_buffer_overflow_code->set_is_pregenerated(true);
2758750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  isolate->set_fp_stubs_generated(true);
2759c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2760c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2761c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
27628432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
2763c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CEntryStub stub(1, kDontSaveFPRegs);
27648432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  Handle<Code> code = stub.GetCode(isolate);
2765c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  code->set_is_pregenerated(true);
2766c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2767c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2768c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
276959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgstatic void JumpIfOOM(MacroAssembler* masm,
277059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                      Register value,
277159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                      Register scratch,
277259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                      Label* oom_label) {
277359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3);
277459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  STATIC_ASSERT(kFailureTag == 3);
277559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ and_(scratch, value, Operand(0xf));
277659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(scratch, Operand(0xf));
277759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ b(eq, oom_label);
277859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
277959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
278059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
278165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CEntryStub::GenerateCore(MacroAssembler* masm,
278265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* throw_normal_exception,
278365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* throw_termination_exception,
278465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* throw_out_of_memory_exception,
278565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              bool do_gc,
27860ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org                              bool always_allocate) {
278765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: result parameter for PerformGC, if any
278865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r4: number of arguments including receiver  (C callee-saved)
278965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r5: pointer to builtin function  (C callee-saved)
279065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r6: pointer to the first argument (C callee-saved)
2791ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = masm->isolate();
279265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
279365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (do_gc) {
279465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Passing r0.
27958e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    __ PrepareCallCFunction(1, 0, r1);
27968e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    __ CallCFunction(ExternalReference::perform_gc_function(isolate),
27978e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org        1, 0);
279865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
279965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
280065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference scope_depth =
2801ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::heap_always_allocate_scope_depth(isolate);
280265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (always_allocate) {
280365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r0, Operand(scope_depth));
280465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r1, MemOperand(r0));
280565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ add(r1, r1, Operand(1));
280665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ str(r1, MemOperand(r0));
280765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
280865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
280965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call C built-in.
281065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0 = argc, r1 = argv
281165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(r4));
281265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r1, Operand(r6));
281365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
281493a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_HOST_ARCH_ARM
281565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int frame_alignment = MacroAssembler::ActivationFrameAlignment();
281665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int frame_alignment_mask = frame_alignment - 1;
281765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (FLAG_debug_code) {
281865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (frame_alignment > kPointerSize) {
281965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      Label alignment_as_expected;
282065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      ASSERT(IsPowerOf2(frame_alignment));
2821378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      __ tst(sp, Operand(frame_alignment_mask));
282265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ b(eq, &alignment_as_expected);
282365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      // Don't use Check here, as it will call Runtime_Abort re-entering here.
282465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ stop("Unexpected alignment");
282565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ bind(&alignment_as_expected);
282665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
282765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
282865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif
282965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
283032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
2831ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
28326d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // To let the GC traverse the return address of the exit frames, we need to
28336d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // know where the return address is. The CEntryStub is unmovable, so
28346d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // we can store the address on the stack to be able to find it again and
28356d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // we never have to restore it, because it will not change.
28360ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // Compute the return address in lr to return to after the jump below. Pc is
28370ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // already at '+ 8' from the current instruction but return is after three
28380ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  // instructions so add another 4 to pc to get the return address.
28397028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
28407028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Prevent literal pool emission before return address.
28417028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Assembler::BlockConstPoolScope block_const_pool(masm);
28427028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    masm->add(lr, pc, Operand(4));
28437028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ str(lr, MemOperand(sp, 0));
28447028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    masm->Jump(r5);
28457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
284665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2847e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ VFPEnsureFPSCRState(r2);
2848e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
284965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (always_allocate) {
285065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1
285165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // though (contain the result).
285265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r2, Operand(scope_depth));
285365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r3, MemOperand(r2));
285465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ sub(r3, r3, Operand(1));
285565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ str(r3, MemOperand(r2));
285665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
285765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
285865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // check for failure result
285965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label failure_returned;
286065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
286165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Lower 2 bits of r2 are 0 iff r0 has failure tag.
286265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r2, r0, Operand(1));
286365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r2, Operand(kFailureTagMask));
286465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &failure_returned);
286565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
286665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Exit C frame and return.
286765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0:r1: result
286865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // sp: stack pointer
286965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // fp: frame pointer
287049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  //  Callee-saved register r4 still holds argc.
287149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ LeaveExitFrame(save_doubles_, r4);
287249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ mov(pc, lr);
287365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
287465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // check if we should retry or throw exception
287565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label retry;
287665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&failure_returned);
287765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
287865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
287965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &retry);
288065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
288165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Special handling of out of memory exceptions.
288259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  JumpIfOOM(masm, r0, ip, throw_out_of_memory_exception);
288365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2884e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Retrieve the pending exception.
288583e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
2886ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                       isolate)));
288765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(ip));
2888e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2889e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // See if we just retrieved an OOM exception.
2890e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  JumpIfOOM(masm, r0, ip, throw_out_of_memory_exception);
2891e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
2892e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Clear the pending exception.
2893e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r3, Operand(isolate->factory()->the_hole_value()));
2894e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
2895e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                       isolate)));
289665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, MemOperand(ip));
289765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
289865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Special handling of termination exceptions which are uncatchable
289965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // by javascript code.
2900ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ cmp(r0, Operand(isolate->factory()->termination_exception()));
290165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, throw_termination_exception);
290265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
290365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle normal exception.
290465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(throw_normal_exception);
290565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
290665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&retry);  // pass last failure (r0) as parameter (r0) when retrying
290765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
290865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
290965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
291065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CEntryStub::Generate(MacroAssembler* masm) {
291165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Called from JavaScript; parameters are on stack as if calling JS function
291265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: number of arguments including receiver
291365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: pointer to builtin function
291465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // fp: frame pointer  (restored after C call)
291565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // sp: stack pointer  (restored as callee's sp after C call)
291665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // cp: current context  (C callee-saved)
291765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
29181510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm);
29191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
292065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result returned in r0 or r0+r1 by default.
292165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
292265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // NOTE: Invocations of builtins may return failure objects
292365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // instead of a proper result. The builtin entry handles
292465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // this by performing a garbage collection and retrying the
292565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // builtin once.
292665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
292783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // Compute the argv pointer in a callee-saved register.
292883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
292983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  __ sub(r6, r6, Operand(kPointerSize));
293083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
293165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Enter the exit frame that transitions from JavaScript to C++.
2932c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FrameScope scope(masm, StackFrame::MANUAL);
2933a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ EnterExitFrame(save_doubles_);
293465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2935f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up argc and the builtin function in callee-saved registers.
293683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  __ mov(r4, Operand(r0));
293783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  __ mov(r5, Operand(r1));
293883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
293965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r4: number of arguments (C callee-saved)
294065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r5: pointer to builtin function (C callee-saved)
294165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r6: pointer to first argument (C callee-saved)
294265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
294365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label throw_normal_exception;
294465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label throw_termination_exception;
294565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label throw_out_of_memory_exception;
294665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
294765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call into the runtime system.
294865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCore(masm,
294965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_normal_exception,
295065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_termination_exception,
295165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_out_of_memory_exception,
295265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               false,
29530ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org               false);
295465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
295565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do space-specific GC and retry runtime call.
295665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCore(masm,
295765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_normal_exception,
295865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_termination_exception,
295965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_out_of_memory_exception,
296065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               true,
29610ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org               false);
296265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
296365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do full GC and retry runtime call one final time.
296465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Failure* failure = Failure::InternalError();
296565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(reinterpret_cast<int32_t>(failure)));
296665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCore(masm,
296765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_normal_exception,
296865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_termination_exception,
296965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_out_of_memory_exception,
297065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               true,
29710ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org               true);
297265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
297365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&throw_out_of_memory_exception);
297465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Set external caught exception to false.
297565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  Isolate* isolate = masm->isolate();
297665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
297765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                                    isolate);
297859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r0, Operand(false, RelocInfo::NONE32));
297965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(r2, Operand(external_caught));
298065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ str(r0, MemOperand(r2));
298165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
298265a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Set pending exception and r0 to out of memory exception.
298359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  Label already_have_failure;
298459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  JumpIfOOM(masm, r0, ip, &already_have_failure);
298559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  Failure* out_of_memory = Failure::OutOfMemoryException(0x1);
298665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
298759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ bind(&already_have_failure);
298865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
298965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                                       isolate)));
299065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ str(r0, MemOperand(r2));
299165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Fall through to the next label.
299265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
299365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&throw_termination_exception);
299465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ ThrowUncatchable(r0);
299565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
299665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&throw_normal_exception);
299765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ Throw(r0);
299865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
299965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
300065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
300165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
300265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: code entry
300365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: function
300465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: receiver
300565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: argc
300665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // [sp+0]: argv
300765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
300804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label invoke, handler_entry, exit;
300965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
30101510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm);
30111510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
301265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Called from C, so do not pop argc and args on exit (preserve sp)
301365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // No need to save register-passed args
301465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Save callee-saved registers (incl. cp and fp), sp, and lr
301565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ stm(db_w, sp, kCalleeSaved | lr.bit());
301665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3017e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Save callee-saved vfp registers.
3018e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
3019e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Set up the reserved register for 0.0.
3020e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vmov(kDoubleRegZero, 0.0);
3021e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ VFPEnsureFPSCRState(r4);
3022ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org
302365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get address of argv, see stm above.
302465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: code entry
302565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: function
302665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: receiver
302765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: argc
3028ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org
3029f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up argv in r4.
3030ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org  int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
3031e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
3032ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org  __ ldr(r4, MemOperand(sp, offset_to_argv));
303365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
303465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Push a frame with special values setup to mark it as an entry frame.
303565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: code entry
303665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: function
303765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: receiver
303865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: argc
303965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r4: argv
3040ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = masm->isolate();
304165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r8, Operand(-1));  // Push a bad frame pointer to fail if it is used.
304265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
304365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r7, Operand(Smi::FromInt(marker)));
304465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r6, Operand(Smi::FromInt(marker)));
3045ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(r5,
304683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org         Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
304765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r5, MemOperand(r5));
304865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Push(r8, r7, r6, r5);
304965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3050f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up frame pointer for the frame to be pushed.
305165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
305265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3053a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // If this is the outermost JS call, set js_entry_sp value.
3054c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label non_outermost_js;
305583e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
3056a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(r5, Operand(ExternalReference(js_entry_sp)));
3057a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r6, MemOperand(r5));
3058ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org  __ cmp(r6, Operand::Zero());
3059c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ b(ne, &non_outermost_js);
3060c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ str(fp, MemOperand(r5));
3061c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
3062c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label cont;
3063c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ b(&cont);
3064c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&non_outermost_js);
3065c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(ip, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
3066c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&cont);
3067c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ push(ip);
3068a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
306904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Jump to a faked try block that does the invoke, with a faked catch
307004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // block that sets the pending exception.
307104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ jmp(&invoke);
30727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
30737028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // Block literal pool emission whilst taking the position of the handler
30747028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // entry. This avoids making the assumption that literal pools are always
30757028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // emitted after an instruction is emitted, rather than before.
30767028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
30777028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Assembler::BlockConstPoolScope block_const_pool(masm);
30787028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ bind(&handler_entry);
30797028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    handler_offset_ = handler_entry.pos();
30807028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Caught exception: Store result (exception) in the pending exception
30817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // field in the JSEnv and return a failure sentinel.  Coming in here the
30827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // fp will be invalid because the PushTryHandler below sets it to 0 to
30837028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // signal the existence of the JSEntry frame.
30847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
30857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                         isolate)));
30867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
308765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r0, MemOperand(ip));
308865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
308965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(&exit);
309065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
309104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Invoke: Link this frame into the handler chain.  There's only one
309204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // handler block in this code object, so its index is 0.
309365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&invoke);
309465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Must preserve r0-r4, r5-r7 are available.
309578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  __ PushTryHandler(StackHandler::JS_ENTRY, 0);
309665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If an exception not caught by another handler occurs, this handler
309765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // returns control to the code after the bl(&invoke) above, which
309865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // restores all kCalleeSaved registers (including cp and fp) to their
309965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // saved values before returning a failure to C.
310065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
310165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Clear any pending exceptions.
3102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(r5, Operand(isolate->factory()->the_hole_value()));
310383e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
3104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                       isolate)));
310565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r5, MemOperand(ip));
310665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
310765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Invoke the function by calling through JS entry trampoline builtin.
310865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Notice that we cannot store a reference to the trampoline code directly in
310965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // this stub, because runtime stubs are not traversed when doing GC.
311065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
311165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Expected registers by Builtins::JSEntryTrampoline
311265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: code entry
311365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: function
311465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: receiver
311565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: argc
311665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r4: argv
311765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (is_construct) {
31187979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
3119ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                      isolate);
312065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(ip, Operand(construct_entry));
312165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
31227979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
312365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(ip, Operand(entry));
312465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
312565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(ip, MemOperand(ip));  // deref address
312665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
312765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Branch and link to JSEntryTrampoline.  We don't use the double underscore
312865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // macro for the add instruction because we don't want the coverage tool
31297028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // inserting instructions here after we read the pc. We block literal pool
31307028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // emission for the same reason.
31317028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
31327028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Assembler::BlockConstPoolScope block_const_pool(masm);
31337028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ mov(lr, Operand(pc));
31347028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    masm->add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
31357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
313665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3137c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Unlink this frame from the handler chain.
3138c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ PopTryHandler();
313965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3140c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&exit);  // r0 holds result
3141c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check if the current stack frame is marked as the outermost JS frame.
3142c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label non_outermost_js_2;
3143c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ pop(r5);
3144c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
3145c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ b(ne, &non_outermost_js_2);
3146ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org  __ mov(r6, Operand::Zero());
3147a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(r5, Operand(ExternalReference(js_entry_sp)));
3148c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ str(r6, MemOperand(r5));
3149c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&non_outermost_js_2);
315065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
315165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Restore the top frame descriptors from the stack.
315265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(r3);
3153ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(ip,
315483e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org         Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
315565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, MemOperand(ip));
315665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
315765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Reset the stack to the callee saved registers.
315865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
315965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
316065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Restore callee-saved registers and return.
316165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef DEBUG
316265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (FLAG_debug_code) {
316365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(lr, Operand(pc));
316465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
316565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif
3166ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org
3167e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Restore callee-saved vfp registers.
3168e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
3169ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org
317065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
317165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
317265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
317365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
31740a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// Uses registers r0 to r4.
31750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// Expected input (depending on whether args are in registers or on the stack):
31760a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// * object: r0 or at sp + 1 * kPointerSize.
31770a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// * function: r1 or at sp.
31780a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org//
31790a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// An inlined call site may have been generated before calling this stub.
31800a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// In this case the offset to the inline site to patch is passed on the stack,
31810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// in the safepoint slot for register r4.
31820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// (See LCodeGen::DoInstanceOfKnownGlobal)
318365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid InstanceofStub::Generate(MacroAssembler* masm) {
31840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Call site inlining and patching implies arguments in registers.
31850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
31860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // ReturnTrueFalse is only implemented for inlined call sites.
31870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck());
31880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
3189023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Fixed register usage throughout the stub:
31909e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  const Register object = r0;  // Object (lhs).
31910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  Register map = r3;  // Map of the object.
31929e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  const Register function = r1;  // Function (rhs).
3193023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  const Register prototype = r4;  // Prototype of the function.
31940a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  const Register inline_site = r9;
3195023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  const Register scratch = r2;
31960a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
3197f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  const int32_t kDeltaToLoadBoolResult = 4 * kPointerSize;
31980a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
3199023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Label slow, loop, is_instance, is_not_instance, not_js_object;
32000a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
3201d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!HasArgsInRegisters()) {
32029e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    __ ldr(object, MemOperand(sp, 1 * kPointerSize));
32039e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    __ ldr(function, MemOperand(sp, 0));
3204023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  }
320565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3206023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Check that the left hand is a JS object and load map.
3207378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfSmi(object, &not_js_object);
32089e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
320965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
32100a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // If there is a call site cache don't look in the global cache, but do the
32110a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // real lookup and update the call site cache.
32120a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  if (!HasCallSiteInlineCheck()) {
32130a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    Label miss;
3214fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
32150a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ b(ne, &miss);
3216fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex);
32170a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ b(ne, &miss);
32180a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
32190a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ Ret(HasArgsInRegisters() ? 0 : 2);
32200a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
32210a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ bind(&miss);
32220a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
322365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
32240a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Get the prototype of the function.
3225394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
322665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
322765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the function prototype is a JS object.
3228378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfSmi(prototype, &slow);
3229023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
323065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
32310a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // Update the global instanceof or call site inlined cache with the current
32320a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // map and function. The cached answer will be set when it is known below.
32330a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  if (!HasCallSiteInlineCheck()) {
32340a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
32350a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
32360a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  } else {
32370a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    ASSERT(HasArgsInRegisters());
32380a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Patch the (relocated) inlined map check.
32390a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
32400a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // The offset was stored in r4 safepoint slot.
32410a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal)
32423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    __ LoadFromSafepointRegisterSlot(scratch, r4);
32430a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ sub(inline_site, lr, scratch);
32440a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Get the map location in scratch and patch it.
32450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ GetRelocatedValueLocation(inline_site, scratch);
3246f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    __ ldr(scratch, MemOperand(scratch));
324741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    __ str(map, FieldMemOperand(scratch, Cell::kValueOffset));
32480a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
324965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
325065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Register mapping: r3 is object map and r4 is function prototype.
325165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get prototype of object into r2.
3252023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
325365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
32540a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  // We don't need map any more. Use it as a scratch register.
32550a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  Register scratch2 = map;
32560a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  map = no_reg;
32570a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
325865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Loop through the prototype chain looking for the function prototype.
32590a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  __ LoadRoot(scratch2, Heap::kNullValueRootIndex);
326065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
3261023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ cmp(scratch, Operand(prototype));
326265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &is_instance);
32630a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  __ cmp(scratch, scratch2);
326465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &is_not_instance);
3265023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
3266023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
326765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&loop);
326865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
326965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&is_instance);
32700a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  if (!HasCallSiteInlineCheck()) {
32710a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ mov(r0, Operand(Smi::FromInt(0)));
32720a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
32730a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  } else {
32740a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Patch the call site to return true.
32750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ LoadRoot(r0, Heap::kTrueValueRootIndex);
32760a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ add(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
32770a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Get the boolean result location in scratch and patch it.
32780a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ GetRelocatedValueLocation(inline_site, scratch);
32790a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ str(r0, MemOperand(scratch));
32800a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
32810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (!ReturnTrueFalseObject()) {
32820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      __ mov(r0, Operand(Smi::FromInt(0)));
32830a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
32840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
3285d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ Ret(HasArgsInRegisters() ? 0 : 2);
328665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
328765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&is_not_instance);
32880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  if (!HasCallSiteInlineCheck()) {
32890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ mov(r0, Operand(Smi::FromInt(1)));
32900a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
32910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  } else {
32920a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Patch the call site to return false.
32930a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ LoadRoot(r0, Heap::kFalseValueRootIndex);
32940a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ add(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
32950a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    // Get the boolean result location in scratch and patch it.
32960a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ GetRelocatedValueLocation(inline_site, scratch);
32970a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ str(r0, MemOperand(scratch));
32980a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
32990a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (!ReturnTrueFalseObject()) {
33000a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      __ mov(r0, Operand(Smi::FromInt(1)));
33010a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
33020a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
3303d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ Ret(HasArgsInRegisters() ? 0 : 2);
3304023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
3305023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Label object_not_null, object_not_null_or_smi;
3306023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ bind(&not_js_object);
3307023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Before null, smi and string value checks, check that the rhs is a function
3308023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // as for a non-function rhs an exception needs to be thrown.
3309378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfSmi(function, &slow);
33100a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE);
3311023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ b(ne, &slow);
3312023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
3313023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Null is not instance of anything.
3314160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ cmp(scratch, Operand(masm->isolate()->factory()->null_value()));
3315023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ b(ne, &object_not_null);
3316023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ mov(r0, Operand(Smi::FromInt(1)));
3317d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ Ret(HasArgsInRegisters() ? 0 : 2);
3318023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
3319023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ bind(&object_not_null);
3320023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Smi values are not instances of anything.
3321378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfNotSmi(object, &object_not_null_or_smi);
3322023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ mov(r0, Operand(Smi::FromInt(1)));
3323d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ Ret(HasArgsInRegisters() ? 0 : 2);
3324023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
3325023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ bind(&object_not_null_or_smi);
3326023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // String values are not instances of anything.
3327023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ IsObjectJSStringType(object, scratch, &slow);
3328023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  __ mov(r0, Operand(Smi::FromInt(1)));
3329d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ Ret(HasArgsInRegisters() ? 0 : 2);
333065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
333165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Slow-case.  Tail call builtin.
3332d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ bind(&slow);
33330a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  if (!ReturnTrueFalseObject()) {
33340a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (HasArgsInRegisters()) {
33350a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      __ Push(r0, r1);
33360a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
33378e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
33380a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  } else {
3339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
3340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
3341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ Push(r0, r1);
3342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
3343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
3344ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org    __ cmp(r0, Operand::Zero());
33450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ LoadRoot(r0, Heap::kTrueValueRootIndex, eq);
33460a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ LoadRoot(r0, Heap::kFalseValueRootIndex, ne);
33470a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    __ Ret(HasArgsInRegisters() ? 0 : 2);
33489e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  }
334965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
335065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
335165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
33526bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) {
33536bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  Label miss;
33546bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  Register receiver;
33556bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (kind() == Code::KEYED_LOAD_IC) {
33566bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // ----------- S t a t e -------------
33576bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- lr    : return address
33586bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r0    : key
33596bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r1    : receiver
33606bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // -----------------------------------
33614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ cmp(r0, Operand(masm->isolate()->factory()->prototype_string()));
33626bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    __ b(ne, &miss);
33636bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    receiver = r1;
33646bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  } else {
33656bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    ASSERT(kind() == Code::LOAD_IC);
33666bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // ----------- S t a t e -------------
33676bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r2    : name
33686bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- lr    : return address
33696bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r0    : receiver
33706bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- sp[0] : receiver
33716bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // -----------------------------------
33726bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    receiver = r0;
33736bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  }
33746bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
33756bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
33766bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  __ bind(&miss);
3377bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  StubCompiler::TailCallBuiltin(
3378bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
33796bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org}
33806bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
33816bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
33826bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgvoid StringLengthStub::Generate(MacroAssembler* masm) {
33836bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  Label miss;
33846bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  Register receiver;
33856bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (kind() == Code::KEYED_LOAD_IC) {
33866bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // ----------- S t a t e -------------
33876bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- lr    : return address
33886bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r0    : key
33896bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r1    : receiver
33906bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // -----------------------------------
33914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ cmp(r0, Operand(masm->isolate()->factory()->length_string()));
33926bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    __ b(ne, &miss);
33936bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    receiver = r1;
33946bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  } else {
33956bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    ASSERT(kind() == Code::LOAD_IC);
33966bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // ----------- S t a t e -------------
33976bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r2    : name
33986bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- lr    : return address
33996bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- r0    : receiver
34006bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    //  -- sp[0] : receiver
34016bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // -----------------------------------
34026bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    receiver = r0;
34036bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  }
34046bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
34056bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  StubCompiler::GenerateLoadStringLength(masm, receiver, r3, r4, &miss,
34066bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org                                         support_wrapper_);
34076bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
34086bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  __ bind(&miss);
3409bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  StubCompiler::TailCallBuiltin(
3410bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
34116bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org}
34126bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
34136bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
3414d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.orgvoid StoreArrayLengthStub::Generate(MacroAssembler* masm) {
3415d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // This accepts as a receiver anything JSArray::SetElementsLength accepts
3416d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // (currently anything except for external arrays which means anything with
3417d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // elements of FixedArray type).  Value must be a number, but only smis are
3418d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // accepted as the most common case.
3419d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Label miss;
3420d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3421d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Register receiver;
3422d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Register value;
3423d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  if (kind() == Code::KEYED_STORE_IC) {
3424d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    // ----------- S t a t e -------------
3425d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- lr    : return address
3426d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- r0    : value
3427d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- r1    : key
3428d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- r2    : receiver
3429d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    // -----------------------------------
34304a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ cmp(r1, Operand(masm->isolate()->factory()->length_string()));
3431d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    __ b(ne, &miss);
3432d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    receiver = r2;
3433d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    value = r0;
3434d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  } else {
3435d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    ASSERT(kind() == Code::STORE_IC);
3436d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    // ----------- S t a t e -------------
3437d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- lr    : return address
3438d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- r0    : value
3439d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- r1    : receiver
3440d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    //  -- r2    : key
3441d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    // -----------------------------------
3442d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    receiver = r1;
3443d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    value = r0;
3444d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  }
3445d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Register scratch = r3;
3446d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3447d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that the receiver isn't a smi.
3448d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ JumpIfSmi(receiver, &miss);
3449d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3450d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that the object is a JS array.
3451d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
3452d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ b(ne, &miss);
3453d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3454d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that elements are FixedArray.
3455d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // We rely on StoreIC_ArrayLength below to deal with all types of
3456d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // fast elements (including COW).
3457d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
3458d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
3459d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ b(ne, &miss);
3460d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3461d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that the array has fast properties, otherwise the length
3462d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // property might have been redefined.
3463d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ ldr(scratch, FieldMemOperand(receiver, JSArray::kPropertiesOffset));
3464d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ ldr(scratch, FieldMemOperand(scratch, FixedArray::kMapOffset));
3465d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ CompareRoot(scratch, Heap::kHashTableMapRootIndex);
3466d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ b(eq, &miss);
3467d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3468d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that value is a smi.
3469d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ JumpIfNotSmi(value, &miss);
3470d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3471d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Prepare tail call to StoreIC_ArrayLength.
3472d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ Push(receiver, value);
3473d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3474d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  ExternalReference ref =
3475d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org      ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
3476d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ TailCallExternalReference(ref, 2, 1);
3477d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3478d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ bind(&miss);
3479d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3480bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  StubCompiler::TailCallBuiltin(
3481bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
3482d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org}
3483d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
3484d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
34850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgRegister InstanceofStub::left() { return r0; }
34860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
34870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
34880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgRegister InstanceofStub::right() { return r1; }
34890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
34900a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
349165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
349265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The displacement is the offset of the last parameter (if any)
349365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // relative to the frame pointer.
34941456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kDisplacement =
349565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      StandardFrameConstants::kCallerSPOffset - kPointerSize;
349665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
349765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the key is a smi.
349865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label slow;
3499378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfNotSmi(r1, &slow);
350065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
350165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if the calling frame is an arguments adaptor frame.
350265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label adaptor;
350365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
350465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
350565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
350665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &adaptor);
350765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
350865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check index against formal parameters count limit passed in
350965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // through register r0. Use unsigned comparison to get negative
351065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // check for free.
351165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r1, r0);
3512d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ b(hs, &slow);
351365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
351465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Read the argument from the stack and return it.
351565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(r3, r0, r1);
3516bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r3, fp, Operand::PointerOffsetFromSmiKey(r3));
351765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(r3, kDisplacement));
351865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Jump(lr);
351965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
352065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Arguments adaptor case: Check index against actual arguments
352165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // limit found in the arguments adaptor frame. Use unsigned
352265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // comparison to get negative check for free.
352365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&adaptor);
352465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
352565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r1, r0);
352665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(cs, &slow);
352765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
352865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Read the argument from the adaptor frame and return it.
352965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(r3, r0, r1);
3530bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r3));
353165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(r3, kDisplacement));
353265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Jump(lr);
353365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
353465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Slow-case: Handle non-smi or out-of-bounds access to arguments
353565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // by calling the runtime system.
353665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow);
353765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(r1);
353865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
353965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
354065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
354165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
35427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
354365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // sp[0] : number of parameters
354465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // sp[4] : receiver displacement
354565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // sp[8] : function
354665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
354765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if the calling frame is an arguments adaptor frame.
35487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label runtime;
35497b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
35507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
35517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
35527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ b(ne, &runtime);
35537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Patch the arguments.length and the parameters pointer in the current frame.
35557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
35567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r2, MemOperand(sp, 0 * kPointerSize));
35577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r3, r3, Operand(r2, LSL, 1));
35587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
35597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r3, MemOperand(sp, 1 * kPointerSize));
35607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&runtime);
35627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
35637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org}
35647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
35677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Stack layout:
35687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //  sp[0] : number of parameters (tagged)
35697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //  sp[4] : address of receiver argument
35707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //  sp[8] : function
35717b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Registers used over whole function:
35727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //  r6 : allocated object (tagged)
35737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //  r9 : mapped parameter count (tagged)
35747b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35757b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
35767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r1 = parameter count (tagged)
35777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Check if the calling frame is an arguments adaptor frame.
35797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label runtime;
35807b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label adaptor_frame, try_allocate;
35817b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
35827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset));
35837b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
35847b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ b(eq, &adaptor_frame);
35857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // No adaptor, parameter count = argument count.
35877b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r2, r1);
35887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ b(&try_allocate);
35897b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35907b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // We have an adaptor frame. Patch the parameters pointer.
35917b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&adaptor_frame);
35927b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset));
35937b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r3, r3, Operand(r2, LSL, 1));
35947b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
35957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r3, MemOperand(sp, 1 * kPointerSize));
35967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
35977b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r1 = parameter count (tagged)
35987b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r2 = argument count (tagged)
35997b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Compute the mapped parameter count = min(r1, r2) in r1.
36007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r1, Operand(r2));
36017b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r1, Operand(r2), LeaveCC, gt);
36027b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&try_allocate);
36047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Compute the sizes of backing store, parameter map, and arguments object.
36067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // 1. Parameter map, has 2 extra words containing context and backing store.
36077b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int kParameterMapHeaderSize =
36087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      FixedArray::kHeaderSize + 2 * kPointerSize;
36097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // If there are no mapped parameters, we do not need the parameter_map.
36107b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r1, Operand(Smi::FromInt(0)));
3611ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org  __ mov(r9, Operand::Zero(), LeaveCC, eq);
36127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne);
36137b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne);
36147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // 2. Backing store.
36167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(r2, LSL, 1));
36177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(FixedArray::kHeaderSize));
36187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // 3. Arguments object.
36207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(Heap::kArgumentsObjectSize));
36217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36227b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Do the allocation of all three objects in one go.
3623f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT);
36247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r0 = address of new object(s) (tagged)
36267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r2 = argument count (tagged)
362746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Get the arguments boilerplate from the current native context into r4.
36287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int kNormalOffset =
36297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
36307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int kAliasedOffset =
36317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
36327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
363346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r4, MemOperand(r8, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
363446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
3635ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org  __ cmp(r1, Operand::Zero());
36367b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r4, MemOperand(r4, kNormalOffset), eq);
36377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r4, MemOperand(r4, kAliasedOffset), ne);
36387b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r0 = address of new object (tagged)
36407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r1 = mapped parameter count (tagged)
36417b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r2 = argument count (tagged)
36427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r4 = address of boilerplate object (tagged)
36437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Copy the JS object part.
36447b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
36457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    __ ldr(r3, FieldMemOperand(r4, i));
36467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    __ str(r3, FieldMemOperand(r0, i));
36477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  }
36487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
3649f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the callee in-object property.
36507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
36517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r3, MemOperand(sp, 2 * kPointerSize));
36527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int kCalleeOffset = JSObject::kHeaderSize +
36537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Heap::kArgumentsCalleeIndex * kPointerSize;
36547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r3, FieldMemOperand(r0, kCalleeOffset));
36557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Use the length (smi tagged) and set that as an in-object property too.
36577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
36587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int kLengthOffset = JSObject::kHeaderSize +
36597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Heap::kArgumentsLengthIndex * kPointerSize;
36607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r2, FieldMemOperand(r0, kLengthOffset));
36617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
3662f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the elements pointer in the allocated arguments object.
36637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // If we allocated a parameter map, r4 will point there, otherwise
36647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // it will point to the backing store.
36657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r4, r0, Operand(Heap::kArgumentsObjectSize));
36667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
36677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r0 = address of new object (tagged)
36697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r1 = mapped parameter count (tagged)
36707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r2 = argument count (tagged)
36717b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r4 = address of parameter map or backing store (tagged)
36727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Initialize parameter map. If there are no mapped arguments, we're done.
36737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label skip_parameter_map;
36747b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r1, Operand(Smi::FromInt(0)));
36757b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Move backing store address to r3, because it is
36767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // expected there when filling in the unmapped arguments.
36777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r3, r4, LeaveCC, eq);
36787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ b(eq, &skip_parameter_map);
36797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36807b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ LoadRoot(r6, Heap::kNonStrictArgumentsElementsMapRootIndex);
36817b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset));
36827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r6, r1, Operand(Smi::FromInt(2)));
36837b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset));
36847b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r8, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize));
36857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r6, r4, Operand(r1, LSL, 1));
36867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r6, r6, Operand(kParameterMapHeaderSize));
36877b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize));
36887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
36897b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Copy the parameter slots and the holes in the arguments.
36907b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // We need to fill in mapped_parameter_count slots. They index the context,
36917b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // where parameters are stored in reverse order, at
36927b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
36937b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // The mapped parameter thus need to get indices
36947b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
36957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
36967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // We loop from right to left.
36977b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label parameters_loop, parameters_test;
36987b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r6, r1);
36997b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r9, MemOperand(sp, 0 * kPointerSize));
37007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
37017b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ sub(r9, r9, Operand(r1));
37027b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
37037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r3, r4, Operand(r6, LSL, 1));
37047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r3, r3, Operand(kParameterMapHeaderSize));
37057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r6 = loop variable (tagged)
37077b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r1 = mapping index (tagged)
37087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r3 = address of backing store (tagged)
37097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r4 = address of parameter map (tagged)
37107b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r5 = temporary scratch (a.o., for address calculation)
37117b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r7 = the hole value
37127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ jmp(&parameters_test);
37137b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&parameters_loop);
37157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ sub(r6, r6, Operand(Smi::FromInt(1)));
37167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r5, Operand(r6, LSL, 1));
37177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r5, r5, Operand(kParameterMapHeaderSize - kHeapObjectTag));
37187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r9, MemOperand(r4, r5));
37197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ sub(r5, r5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
37207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r7, MemOperand(r3, r5));
37217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(Smi::FromInt(1)));
37227b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&parameters_test);
37237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r6, Operand(Smi::FromInt(0)));
37247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ b(ne, &parameters_loop);
37257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&skip_parameter_map);
37277b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r2 = argument count (tagged)
37287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r3 = address of backing store (tagged)
37297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // r5 = scratch
37307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Copy arguments header and remaining slots (if there are any).
37317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex);
37327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset));
37337b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset));
37347b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37357b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label arguments_loop, arguments_test;
37367b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(r9, r1);
37377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r4, MemOperand(sp, 1 * kPointerSize));
37387b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ sub(r4, r4, Operand(r9, LSL, 1));
37397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ jmp(&arguments_test);
37407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37417b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&arguments_loop);
37427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ sub(r4, r4, Operand(kPointerSize));
37437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r6, MemOperand(r4, 0));
37447b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r5, r3, Operand(r9, LSL, 1));
37457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize));
37467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r9, r9, Operand(Smi::FromInt(1)));
37477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&arguments_test);
37497b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ cmp(r9, Operand(r2));
37507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ b(lt, &arguments_loop);
37517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Return and remove the on-stack parameters.
37537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(sp, sp, Operand(3 * kPointerSize));
37547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ Ret();
37557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Do the runtime call to allocate the arguments object.
3757f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // r2 = argument count (tagged)
37587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&runtime);
37597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ str(r2, MemOperand(sp, 0 * kPointerSize));  // Patch argument count.
37607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
37617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org}
37627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
37647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
37657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // sp[0] : number of parameters
37667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // sp[4] : receiver displacement
37677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // sp[8] : function
37687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Check if the calling frame is an arguments adaptor frame.
376965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label adaptor_frame, try_allocate, runtime;
377065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
377165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
377265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
377365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &adaptor_frame);
377465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
377565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the length from the frame.
377665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r1, MemOperand(sp, 0));
377765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(&try_allocate);
377865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
377965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Patch the arguments.length and the parameters pointer.
378065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&adaptor_frame);
378165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
378265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, MemOperand(sp, 0));
3783bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1));
378465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
378565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, MemOperand(sp, 1 * kPointerSize));
378665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
378765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Try the new space allocation. Start out with computing the size
378865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // of the arguments object and the elements array in words.
378965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label add_arguments_object;
379065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&try_allocate);
3791bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r1, SetCC);
379265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &add_arguments_object);
379365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
379465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&add_arguments_object);
37957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
379665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
379765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do the allocation of both objects in one go.
3798f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(r1, r0, r2, r3, &runtime,
3799f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
380065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
380146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Get the arguments boilerplate from the current native context.
380246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
380346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
38047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ldr(r4, MemOperand(r4, Context::SlotOffset(
38057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
380665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
380765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy the JS object part.
3808fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  __ CopyFields(r0, r4, d0, JSObject::kHeaderSize / kPointerSize);
380965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
381065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the length (smi tagged) and set that as an in-object property too.
3811ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
381265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
3813ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize +
38147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Heap::kArgumentsLengthIndex * kPointerSize));
381565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
381665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If there are no actual arguments, we're done.
381765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label done;
381859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r1, Operand::Zero());
381965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &done);
382065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
382165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the parameters pointer from the stack.
382265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r2, MemOperand(sp, 1 * kPointerSize));
382365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3824f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the elements pointer in the allocated arguments object and
382565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // initialize the header in the elements fixed array.
38267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict));
382765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
382865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
382965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
383065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset));
3831bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r1);
383265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
383365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy the fixed array slots.
383465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label loop;
3835f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up r4 to point to the first array slot.
383665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
383765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
383865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Pre-decrement r2 with kPointerSize on each iteration.
383965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Pre-decrement in order to skip receiver.
384065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex));
384165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Post-increment r4 with kPointerSize on each iteration.
384265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, MemOperand(r4, kPointerSize, PostIndex));
384365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(r1, r1, Operand(1));
384459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r1, Operand::Zero());
384565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &loop);
384665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
384765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return and remove the on-stack parameters.
384865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
384965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(3 * kPointerSize));
385065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
385165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
385265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do the runtime call to allocate the arguments object.
385365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
38547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
385565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
385665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
385765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
385865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid RegExpExecStub::Generate(MacroAssembler* masm) {
385965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Just jump directly to runtime if native RegExp is not selected at compile
386065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // time or if regexp entry in generated code is turned off runtime switch or
386165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // at compilation.
386265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef V8_INTERPRETED_REGEXP
386365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
386465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#else  // V8_INTERPRETED_REGEXP
386565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
386665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack frame on entry.
386765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[0]: last_match_info (expected JSArray)
386865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[4]: previous index
386965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[8]: subject string
387065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[12]: JSRegExp object
387165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
38721456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kLastMatchInfoOffset = 0 * kPointerSize;
38731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kPreviousIndexOffset = 1 * kPointerSize;
38741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kSubjectOffset = 2 * kPointerSize;
38751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kJSRegExpOffset = 3 * kPointerSize;
387665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
387771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  Label runtime;
387865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Allocation of registers for this function. These are in callee save
387965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // registers and will be preserved by the call to the native RegExp code, as
388065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // this code is called using the normal C calling convention. When calling
388165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // directly from generated code the native RegExp code will not do a GC and
388265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // therefore the content of these registers are safe to use after the call.
388365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register subject = r4;
388465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register regexp_data = r5;
388565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register last_match_info_elements = r6;
388665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
388765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Ensure that a RegExp stack is allocated.
3888ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = masm->isolate();
388965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference address_of_regexp_stack_memory_address =
3890ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::address_of_regexp_stack_memory_address(isolate);
389165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference address_of_regexp_stack_memory_size =
3892ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::address_of_regexp_stack_memory_size(isolate);
389365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(address_of_regexp_stack_memory_size));
389465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(r0, 0));
389559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
389665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &runtime);
389765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
389865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the first argument is a JSRegExp object.
389965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(sp, kJSRegExpOffset));
39007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(r0, &runtime);
390165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
390265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &runtime);
390365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
390465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the RegExp has been compiled (data contains a fixed array).
390565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset));
390665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (FLAG_debug_code) {
3907bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ SmiTst(regexp_data);
3908594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected);
390965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE);
3910594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
391165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
391265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
391365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // regexp_data: RegExp data (FixedArray)
391465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
391565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
391665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
391765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &runtime);
391865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
391965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // regexp_data: RegExp data (FixedArray)
392065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the number of captures fit in the static offsets vector buffer.
392165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r2,
392265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
392371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check (number_of_captures + 1) * 2 <= offsets vector size
392471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Or          number_of_captures * 2 <= offsets vector size - 2
392571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Multiplying by 2 comes for free since r2 is smi-tagged.
392665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
392765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
392871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
392971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
393065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(hi, &runtime);
393165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
39324668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Reset offset for possibly sliced string.
393359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r9, Operand::Zero());
393471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(subject, MemOperand(sp, kSubjectOffset));
393571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfSmi(subject, &runtime);
393671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(r3, subject);  // Make a copy of the original subject string.
393765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
393865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
393971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // subject: subject string
394071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // r3: subject string
394171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // r0: subject string instance type
394271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // regexp_data: RegExp data (FixedArray)
394371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Handle subject string according to its encoding and representation:
394471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (1) Sequential string?  If yes, go to (5).
394571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (2) Anything but sequential or cons?  If yes, go to (6).
394671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (3) Cons string.  If the string is flat, replace subject with first string.
394771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  //     Otherwise bailout.
394871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (4) Is subject external?  If yes, go to (7).
394971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (5) Sequential string.  Load regexp code according to encoding.
395071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (E) Carry on.
395171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  /// [...]
395271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
395371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Deferred code at the end of the stub:
395471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (6) Not a long external string?  If yes, go to (8).
395571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (7) External string.  Make it, offset-wise, look like a sequential string.
395671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  //     Go to (5).
395771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (8) Short external string or not a string?  If yes, bail out to runtime.
395871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (9) Sliced string.  Replace subject with parent.  Go to (4).
395971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
396071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  Label seq_string /* 5 */, external_string /* 7 */,
396171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org        check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
396271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org        not_long_external /* 8 */;
396371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
396471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (1) Sequential string?  If yes, go to (5).
39651b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ and_(r1,
39661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          r0,
39671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          Operand(kIsNotStringMask |
39681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                  kStringRepresentationMask |
39691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                  kShortExternalStringMask),
39701b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          SetCC);
397165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
397271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(eq, &seq_string);  // Go to (5).
397365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
397471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (2) Anything but sequential or cons?  If yes, go to (6).
397580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kConsStringTag < kExternalStringTag);
397680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
39771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
39781b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
39794668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ cmp(r1, Operand(kExternalStringTag));
398071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(ge, &not_seq_nor_cons);  // Go to (6).
39811b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
398271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (3) Cons string.  Check that it's flat.
398371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Replace subject with first string and reload instance type.
398465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
39854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ CompareRoot(r0, Heap::kempty_stringRootIndex);
398665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &runtime);
398765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
398871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
398971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (4) Is subject external?  If yes, go to (7).
399071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&check_underlying);
399165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
399265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
399365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
399465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r0, Operand(kStringRepresentationMask));
399571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // The underlying external string is never a short external string.
399671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
399771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
399871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(ne, &external_string);  // Go to (7).
39991b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
400071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (5) Sequential string.  Load regexp code according to encoding.
400165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&seq_string);
400271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // subject: sequential subject string (or look-alike, external string)
400371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // r3: original subject string
400471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Load previous index and check range before r3 is overwritten.  We have to
400571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // use r3 instead of subject here because subject might have been only made
400671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // to look like a sequential string when it actually is an external string.
400771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(r1, MemOperand(sp, kPreviousIndexOffset));
400871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfNotSmi(r1, &runtime);
400971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset));
401071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(r3, Operand(r1));
401171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(ls, &runtime);
4012bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r1);
401371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
4014e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  STATIC_ASSERT(4 == kOneByteStringTag);
401565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kTwoByteStringTag == 0);
401665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(r0, r0, Operand(kStringEncodingMask));
401765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r3, Operand(r0, ASR, 2), SetCC);
401865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
401965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
402065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
402171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (E) Carry on.  String handling is done.
402271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // r7: irregexp code
402365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the irregexp code has been generated for the actual string
402465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // encoding. If it has, the field contains a code object otherwise it contains
4025ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  // a smi (code flushing support).
4026ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  __ JumpIfSmi(r7, &runtime);
402765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
402865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: previous index
4029badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
403065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r7: code
403165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // subject: Subject string
403265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // regexp_data: RegExp data (FixedArray)
403365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // All checks done. Now push arguments for native regexp code.
40347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2);
403565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4036ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Isolates: note we add an additional parameter here (isolate pointer).
403715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  const int kRegExpExecuteArguments = 9;
40381456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kParameterRegisters = 4;
403949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
404049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
404149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Stack pointer now points to cell where return address is to be written.
404249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Arguments are before that on the stack or in registers.
404365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
404415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 9 (sp[20]): Pass current isolate address.
404532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ mov(r0, Operand(ExternalReference::isolate_address(isolate)));
404615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ str(r0, MemOperand(sp, 5 * kPointerSize));
4047ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
404815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript.
404965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(1));
405015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ str(r0, MemOperand(sp, 4 * kPointerSize));
405165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
405215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area.
405365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(address_of_regexp_stack_memory_address));
405465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(r0, 0));
405565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r2, Operand(address_of_regexp_stack_memory_size));
405665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r2, MemOperand(r2, 0));
405765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r0, r0, Operand(r2));
405815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ str(r0, MemOperand(sp, 3 * kPointerSize));
405915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
406015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 6: Set the number of capture registers to zero to force global
406115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // regexps to behave as non-global.  This does not affect non-global regexps.
406259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r0, Operand::Zero());
406349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ str(r0, MemOperand(sp, 2 * kPointerSize));
406465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
406549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Argument 5 (sp[4]): static offsets vector buffer.
4066ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(r0,
4067ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org         Operand(ExternalReference::address_of_static_offsets_vector(isolate)));
406849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ str(r0, MemOperand(sp, 1 * kPointerSize));
406965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
407065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // For arguments 4 and 3 get string length, calculate start of string data and
407165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // calculate the shift of the index (0 for ASCII and 1 for two byte).
4072c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(r8, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
407365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ eor(r3, r3, Operand(1));
40744668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Load the length from the original subject string from the previous stack
40754668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // frame. Therefore we have to use fp, which points exactly to two pointer
40764668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // sizes below the previous sp. (Because creating a new stack frame pushes
40774668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
40781805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
40794668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // If slice offset is not 0, load the length from the original sliced string.
40804668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Argument 4, r3: End of string data
40814668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Argument 3, r2: Start of string data
40824668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Prepare start and end index of the input.
40834668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ add(r9, r8, Operand(r9, LSL, r3));
408465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r2, r9, Operand(r1, LSL, r3));
40854668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
40861805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ ldr(r8, FieldMemOperand(subject, String::kLengthOffset));
4087bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r8);
40884668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ add(r3, r9, Operand(r8, LSL, r3));
408965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
409065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Argument 2 (r1): Previous index.
409165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Already there
409265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
409365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Argument 1 (r0): Subject string.
40941805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ mov(r0, subject);
409565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
409665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate the code entry and call it.
409765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
409849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  DirectCEntryStub stub;
409949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  stub.GenerateCall(masm, r7);
410049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
410149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ LeaveExitFrame(false, no_reg);
410265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
410365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: result
410465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // subject: subject string (callee saved)
410565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // regexp_data: RegExp data (callee saved)
410665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // last_match_info_elements: Last match info elements (callee saved)
410765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check the result.
410865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label success;
410915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ cmp(r0, Operand(1));
411015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // We expect exactly one result since we force the called regexp to behave
411115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // as non-global.
411265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &success);
411365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label failure;
41141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE));
411565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &failure);
41161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
411765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If not exception it can only be retry. Handle that in the runtime system.
411865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &runtime);
411965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result must now be exception. If there is no pending exception already a
412065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // stack overflow (on the backtrack stack) was detected in RegExp code but
412165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // haven't created the exception yet. Handle that in the runtime system.
412265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
4123c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(r1, Operand(isolate->factory()->the_hole_value()));
412483e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
4125ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                       isolate)));
412649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ ldr(r0, MemOperand(r2, 0));
41271805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ cmp(r0, r1);
412865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &runtime);
412949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
413049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ str(r1, MemOperand(r2, 0));  // Clear pending exception.
413149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
413249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Check if the exception is a termination. If so, throw as uncatchable.
41331805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
41341805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
413549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  Label termination_exception;
413649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ b(eq, &termination_exception);
413749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
413865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ Throw(r0);
413949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
414049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ bind(&termination_exception);
414165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ ThrowUncatchable(r0);
414249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
414365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&failure);
414465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // For failure and exception return null.
4145160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ mov(r0, Operand(masm->isolate()->factory()->null_value()));
414665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(4 * kPointerSize));
414765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
414865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
414965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Process the result from the native regexp code.
415065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&success);
415165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r1,
415265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
415365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate number of capture registers (number_of_captures + 1) * 2.
415471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Multiplying by 2 comes for free since r1 is smi-tagged.
415565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
415665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
415765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r1, r1, Operand(2));  // r1 was a smi.
415865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
415971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
416071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfSmi(r0, &runtime);
416171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ CompareObjectType(r0, r2, r2, JS_ARRAY_TYPE);
416271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(ne, &runtime);
416371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check that the JSArray is in fast case.
416471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(last_match_info_elements,
416571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org         FieldMemOperand(r0, JSArray::kElementsOffset));
416671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
416771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex);
416871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(ne, &runtime);
416971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check that the last match info has space for the capture registers and the
417071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // additional information.
417171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(r0,
417271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org         FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
417371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ add(r2, r1, Operand(RegExpImpl::kLastMatchOverhead));
4174bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ cmp(r2, Operand::SmiUntag(r0));
417571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(gt, &runtime);
417671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
417765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: number of capture registers
417865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r4: subject string
417965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Store the capture count.
4180bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTag(r2, r1);
418165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r2, FieldMemOperand(last_match_info_elements,
418265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                             RegExpImpl::kLastCaptureCountOffset));
418365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Store last subject and last input.
418465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(subject,
418565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         FieldMemOperand(last_match_info_elements,
418665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                         RegExpImpl::kLastSubjectOffset));
4187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(r2, subject);
4188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ RecordWriteField(last_match_info_elements,
4189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      RegExpImpl::kLastSubjectOffset,
419071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org                      subject,
4191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      r7,
4192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      kLRHasNotBeenSaved,
4193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      kDontSaveFPRegs);
419471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(subject, r2);
419565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(subject,
419665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         FieldMemOperand(last_match_info_elements,
419765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                         RegExpImpl::kLastInputOffset));
4198c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ RecordWriteField(last_match_info_elements,
4199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      RegExpImpl::kLastInputOffset,
4200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      subject,
4201c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      r7,
4202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      kLRHasNotBeenSaved,
4203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      kDontSaveFPRegs);
420465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
420565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the static offsets vector filled by the native regexp code.
420665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference address_of_static_offsets_vector =
4207ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::address_of_static_offsets_vector(isolate);
420865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r2, Operand(address_of_static_offsets_vector));
420965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
421065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: number of capture registers
421165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: offsets vector
421265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label next_capture, done;
421365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Capture register counter starts from number of capture registers and
421465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // counts down until wraping after zero.
421565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r0,
421665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         last_match_info_elements,
421765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag));
421865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&next_capture);
421965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(r1, r1, Operand(1), SetCC);
422065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(mi, &done);
422165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Read the value from the static offsets vector buffer.
422265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex));
422365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Store the smi value in the last match info.
4224bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTag(r3);
422565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
422665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&next_capture);
422765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
422865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
422965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return last match info.
423065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset));
423165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(4 * kPointerSize));
423265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
423365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
423471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Do the runtime call to execute the regexp.
423571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&runtime);
423671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
423771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
423871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Deferred code for string handling.
423971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (6) Not a long external string?  If yes, go to (8).
424071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&not_seq_nor_cons);
424171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Compare flags are still set.
424271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(gt, &not_long_external);  // Go to (8).
424371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
424471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (7) External string.  Make it, offset-wise, look like a sequential string.
42451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ bind(&external_string);
42461b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
42471b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
42481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (FLAG_debug_code) {
42491b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Assert that we do not have a cons or slice (indirect strings) here.
42501b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Sequential strings have already been ruled out.
42511b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    __ tst(r0, Operand(kIsIndirectStringMask));
4252594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kExternalStringExpectedButNotFound);
42531b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
42541b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ ldr(subject,
42551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org         FieldMemOperand(subject, ExternalString::kResourceDataOffset));
42561b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Move the pointer so that offset-wise, it looks like a sequential string.
4257fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
42581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ sub(subject,
42591b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org         subject,
42601b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
426171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ jmp(&seq_string);    // Go to (5).
42621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
426371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (8) Short external string or not a string?  If yes, bail out to runtime.
426471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&not_long_external);
426571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
426671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask));
426771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ b(ne, &runtime);
426871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
426971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (9) Sliced string.  Replace subject with parent.  Go to (4).
427071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Load offset into r9 and replace subject string with parent.
427171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset));
4272bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r9);
427371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
427471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ jmp(&check_underlying);  // Go to (4).
427565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif  // V8_INTERPRETED_REGEXP
427665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
427765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
427865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4279a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid RegExpConstructResultStub::Generate(MacroAssembler* masm) {
4280a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kMaxInlineLength = 100;
4281a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label slowcase;
4282a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label done;
4283160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  Factory* factory = masm->isolate()->factory();
4284160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
4285a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r1, MemOperand(sp, kPointerSize * 2));
4286a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  STATIC_ASSERT(kSmiTag == 0);
4287a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
42887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(r1, &slowcase);
4289a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ cmp(r1, Operand(Smi::FromInt(kMaxInlineLength)));
4290a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(hi, &slowcase);
4291a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Smi-tagging is equivalent to multiplying by 2.
4292a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Allocate RegExpResult followed by FixedArray with size in ebx.
4293a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // JSArray:   [Map][empty properties][Elements][Length-smi][index][input]
4294a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Elements:  [Map][Length][..elements..]
4295a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Size of JSArray with two in-object properties and the header of a
4296a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // FixedArray.
4297a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  int objects_size =
4298a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
4299bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r5, r1);
4300a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r2, r5, Operand(objects_size));
4301f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(
4302a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      r2,  // In: Size, in words.
4303a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      r0,  // Out: Start of allocation (tagged).
4304a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      r3,  // Scratch register.
4305a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      r4,  // Scratch register.
4306a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      &slowcase,
4307a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
4308a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r0: Start of allocated area, object-tagged.
4309a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r1: Number of elements in array, as smi.
4310a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r5: Number of elements, untagged.
4311a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4312a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set JSArray map to global.regexp_result_map().
4313a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set empty properties FixedArray.
4314a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set elements to point to FixedArray allocated right after the JSArray.
4315a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Interleave operations for better latency.
431646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
4317a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r3, r0, Operand(JSRegExpResult::kSize));
4318160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ mov(r4, Operand(factory->empty_fixed_array()));
431946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset));
4320a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
4321a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX));
4322a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
4323a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
4324a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4325a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set input, index and length fields from arguments.
4326a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r1, MemOperand(sp, kPointerSize * 0));
4327fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ ldr(r2, MemOperand(sp, kPointerSize * 1));
4328fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ ldr(r6, MemOperand(sp, kPointerSize * 2));
4329a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r1, FieldMemOperand(r0, JSRegExpResult::kInputOffset));
4330fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ str(r2, FieldMemOperand(r0, JSRegExpResult::kIndexOffset));
4331fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ str(r6, FieldMemOperand(r0, JSArray::kLengthOffset));
4332a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4333a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Fill out the elements FixedArray.
4334a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r0: JSArray, tagged.
4335a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r3: FixedArray, tagged.
4336a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r5: Number of elements in array, untagged.
4337a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4338a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set map.
4339160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  __ mov(r2, Operand(factory->fixed_array_map()));
4340a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset));
4341a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set FixedArray length.
4342bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTag(r6, r5);
4343a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r6, FieldMemOperand(r3, FixedArray::kLengthOffset));
434456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Fill contents of fixed-array with undefined.
434556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
4346a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
434756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Fill fixed array elements with undefined.
4348a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r0: JSArray, tagged.
434956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // r2: undefined.
4350a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r3: Start of elements in FixedArray.
4351a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r5: Number of elements to fill.
4352a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label loop;
435359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r5, Operand::Zero());
4354a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&loop);
4355fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ b(le, &done);  // Jump if r5 is negative or zero.
4356a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ sub(r5, r5, Operand(1), SetCC);
4357a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r2, MemOperand(r3, r5, LSL, kPointerSizeLog2));
4358a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ jmp(&loop);
4359a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4360a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&done);
4361a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(sp, sp, Operand(3 * kPointerSize));
4362a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Ret();
4363a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4364a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&slowcase);
4365a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
4366a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
4367a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4368a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
43694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgstatic void GenerateRecordCallTarget(MacroAssembler* masm) {
43704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Cache the called function in a global property cell.  Cache states
43714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // are uninitialized, monomorphic (indicated by a JSFunction), and
43724a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // megamorphic.
43734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // r1 : the function to call
43744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // r2 : cache cell for call target
43754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label initialize, done, miss, megamorphic, not_array_function;
43764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
43774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
43784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            masm->isolate()->heap()->undefined_value());
43794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
43804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org            masm->isolate()->heap()->the_hole_value());
43814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
43824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Load the cache state into r3.
438341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
43844a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
43854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // A monomorphic cache hit or an already megamorphic state: invoke the
43864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // function without changing the state.
43874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(r3, r1);
43884a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ b(eq, &done);
43894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
4390bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // If we came here, we need to see if we are the array function.
4391bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // If we didn't have a matching function, and we didn't find the megamorph
4392bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // sentinel, then we have in the cell either some other function or an
4393bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // AllocationSite. Do a map check on the object in ecx.
4394bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Handle<Map> allocation_site_map(
4395bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm->isolate()->heap()->allocation_site_map(),
4396bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm->isolate());
4397bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ ldr(r5, FieldMemOperand(r3, 0));
4398bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
4399bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ b(ne, &miss);
44001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
44014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Make sure the function is the Array() function
44024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadArrayFunction(r3);
44034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(r1, r3);
44044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ b(ne, &megamorphic);
44054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ jmp(&done);
44064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
44074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&miss);
44084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
44094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
44104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // megamorphic.
44114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
44124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ b(eq, &initialize);
44134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // MegamorphicSentinel is an immortal immovable object (undefined) so no
44144a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // write-barrier is needed.
44154a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&megamorphic);
44164a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
441741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ str(ip, FieldMemOperand(r2, Cell::kValueOffset));
44184e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ jmp(&done);
44194a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
44204a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // An uninitialized cache is patched with the function or sentinel to
44214a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // indicate the ElementsKind if function is the Array constructor.
44224a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&initialize);
44234a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Make sure the function is the Array() function
44244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadArrayFunction(r3);
44254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(r1, r3);
44264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ b(ne, &not_array_function);
44274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
4428bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // The target function is the Array constructor,
4429bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Create an AllocationSite if we don't already have it, store it in the cell
4430bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  {
4431bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
4432bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
443367233eb8592c3336a5489ddca147878265df3ab7jkummerow@chromium.org    __ SmiTag(r0);
4434bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ push(r0);
4435bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ push(r1);
4436bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ push(r2);
4437bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
4438bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    CreateAllocationSiteStub create_stub;
4439bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ CallStub(&create_stub);
4440bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
4441bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ pop(r2);
4442bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ pop(r1);
4443bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ pop(r0);
444467233eb8592c3336a5489ddca147878265df3ab7jkummerow@chromium.org    __ SmiUntag(r0);
4445bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
44464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ b(&done);
44474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
44484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&not_array_function);
444941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ str(r1, FieldMemOperand(r2, Cell::kValueOffset));
44504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // No need for a write barrier here - cells are rescanned.
44514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
44524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&done);
44534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
44544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
44554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
445665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CallFunctionStub::Generate(MacroAssembler* masm) {
4457c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  // r1 : the function to call
4458fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r2 : cache cell for call target
445934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Label slow, non_function;
446065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
446140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // The receiver might implicitly be the global object. This is
446240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // indicated by passing the hole as the receiver to the call
446340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // function stub.
446440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (ReceiverMightBeImplicit()) {
446540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    Label call;
446665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Get the receiver from the stack.
446765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // function, receiver [, arguments]
446840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ ldr(r4, MemOperand(sp, argc_ * kPointerSize));
446940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    // Call as function is indicated with the hole.
447040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
447140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ b(ne, &call);
447240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    // Patch the receiver on the stack with the global receiver object.
447346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    __ ldr(r3,
447446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org           MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
447588d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset));
447688d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    __ str(r3, MemOperand(sp, argc_ * kPointerSize));
447740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ bind(&call);
447865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
447965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
448065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the function is really a JavaScript function.
448165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: pushed function (to be verified)
448234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ JumpIfSmi(r1, &non_function);
448365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the map of the function object.
448488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
448565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &slow);
448665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
448788d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  if (RecordCallTarget()) {
44881510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    GenerateRecordCallTarget(masm);
448988d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  }
449088d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org
449165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fast-case: Invoke the function now.
449265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: pushed function
449365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ParameterCount actual(argc_);
449440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
449540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (ReceiverMightBeImplicit()) {
449640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    Label call_as_function;
449740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
449840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ b(eq, &call_as_function);
4499d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ InvokeFunction(r1,
4500d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      actual,
4501d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      JUMP_FUNCTION,
4502d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      NullCallWrapper(),
4503d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      CALL_AS_METHOD);
450440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ bind(&call_as_function);
450540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  }
450640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ InvokeFunction(r1,
450740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    actual,
450840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    JUMP_FUNCTION,
450940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    NullCallWrapper(),
451040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    CALL_AS_FUNCTION);
451165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
451265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Slow-case: Non-function called.
451365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow);
451488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  if (RecordCallTarget()) {
451588d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    // If there is a call target cache, mark it megamorphic in the
451688d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    // non-function case.  MegamorphicSentinel is an immortal immovable
451788d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    // object (undefined) so no write barrier is needed.
451888d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
451988d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org              masm->isolate()->heap()->undefined_value());
452088d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org    __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
452141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    __ str(ip, FieldMemOperand(r2, Cell::kValueOffset));
452288d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  }
452334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Check for function proxy.
452488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org  __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE));
452534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ b(ne, &non_function);
452634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ push(r1);  // put proxy as additional argument
452759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32));
452859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r2, Operand::Zero());
452934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY);
4530c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ SetCallKind(r5, CALL_AS_METHOD);
453134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  {
453234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    Handle<Code> adaptor =
453334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org      masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
453434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ Jump(adaptor, RelocInfo::CODE_TARGET);
453534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
453634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
453765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
453865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // of the original receiver from the call site).
453934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ bind(&non_function);
454065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, MemOperand(sp, argc_ * kPointerSize));
4541f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ mov(r0, Operand(argc_));  // Set up the number of arguments.
454259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r2, Operand::Zero());
454365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
4544717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  __ SetCallKind(r5, CALL_AS_METHOD);
45457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
454665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org          RelocInfo::CODE_TARGET);
454765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
454865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
454965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4550fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgvoid CallConstructStub::Generate(MacroAssembler* masm) {
4551fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r0 : number of arguments
4552fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r1 : the function to call
4553fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r2 : cache cell for call target
4554fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Label slow, non_function_call;
4555fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4556fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Check that the function is not a smi.
4557fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ JumpIfSmi(r1, &non_function_call);
4558fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Check that the function is a JSFunction.
4559fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
4560fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ b(ne, &slow);
4561fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4562fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  if (RecordCallTarget()) {
45631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    GenerateRecordCallTarget(masm);
4564fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  }
4565fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4566fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Jump to the function-specific construct stub.
45671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Register jmp_reg = r3;
45684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
45694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldr(jmp_reg, FieldMemOperand(jmp_reg,
45704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                  SharedFunctionInfo::kConstructStubOffset));
45714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
4572fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4573fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r0: number of arguments
4574fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r1: called object
4575fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // r3: object type
4576fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Label do_call;
4577fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ bind(&slow);
4578fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE));
4579fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ b(ne, &non_function_call);
4580fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
4581fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ jmp(&do_call);
4582fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4583fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ bind(&non_function_call);
4584fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
4585fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ bind(&do_call);
4586fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Set expected number of arguments to zero (not changing r0).
458759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r2, Operand::Zero());
4588fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ SetCallKind(r5, CALL_AS_METHOD);
4589fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
4590fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org          RelocInfo::CODE_TARGET);
4591fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org}
4592fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
4593fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
459465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// StringCharCodeAtGenerator
459565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
459665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label flat_string;
459765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label ascii_string;
459865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label got_char_code;
45994668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Label sliced_string;
460065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
460165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the receiver is a smi trigger the non-string case.
4602378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfSmi(object_, receiver_not_string_);
460365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
460465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fetch the instance type of the receiver into result register.
460565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
460665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
460765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the receiver is not a string trigger the non-string case.
460865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(result_, Operand(kIsNotStringMask));
460965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, receiver_not_string_);
461065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
461165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the index is non-smi trigger the non-smi case.
4612378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ JumpIfNotSmi(index_, &index_not_smi_);
461365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&got_smi_index_);
461465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
461565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check for index out of range.
461665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset));
4617c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ cmp(ip, Operand(index_));
461865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ls, index_out_of_range_);
461965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4620bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(index_);
46211b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
46221b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  StringCharLoadGenerator::Generate(masm,
46231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                    object_,
46241b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                    index_,
46251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                    result_,
46261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                    &call_runtime_);
462765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4628bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTag(result_);
462965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&exit_);
463065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
463165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
463265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
463365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharCodeAtGenerator::GenerateSlow(
4634c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
4635c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    const RuntimeCallHelper& call_helper) {
4636594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
463765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
463865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Index is not a smi.
463965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&index_not_smi_);
464065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If index is a heap number, try converting it to an integer.
464165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CheckMap(index_,
4642c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org              result_,
464365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org              Heap::kHeapNumberMapRootIndex,
464465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org              index_not_number_,
4645c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org              DONT_DO_SMI_CHECK);
464665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.BeforeCall(masm);
4647c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ push(object_);
464865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(index_);  // Consumed by runtime conversion function.
464965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
465065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
465165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
465265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
465365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // NumberToSmi discards numbers that are not exact integers.
465465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CallRuntime(Runtime::kNumberToSmi, 1);
465565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
465665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Save the conversion result before the pop instructions below
465765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // have a chance to overwrite it.
4658c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ Move(index_, r0);
465965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(object_);
466065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Reload the instance type.
466165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
466265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
466365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.AfterCall(masm);
466465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If index is still not a smi, it must be out of range.
4665c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ JumpIfNotSmi(index_, index_out_of_range_);
466665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Otherwise, return to the fast path.
466765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&got_smi_index_);
466865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
466965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call runtime. We get here when the receiver is a string and the
467065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // index is a number, but the code of getting the actual character
467165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // is too complex (e.g., when the string needs to be flattened).
467265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&call_runtime_);
467365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.BeforeCall(masm);
4674bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTag(index_);
467565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Push(object_, index_);
467665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CallRuntime(Runtime::kStringCharCodeAt, 2);
467765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Move(result_, r0);
467865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.AfterCall(masm);
467965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&exit_);
468065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4681594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
468265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
468365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
468465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
468565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// -------------------------------------------------------------------------
468665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// StringCharFromCodeGenerator
468765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
468865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
468965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fast case of Heap::LookupSingleCharacterStringFromCode.
469065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
469165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiShiftSize == 0);
469259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1));
469365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(code_,
469465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Operand(kSmiTagMask |
469559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                 ((~String::kMaxOneByteCharCode) << kSmiTagSize)));
4696378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org  __ b(ne, &slow_case_);
469765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
469865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
4699badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // At this point code register contains smi tagged ASCII char code.
4700bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(result_, result_, Operand::PointerOffsetFromSmiKey(code_));
470165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
4702fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
470365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &slow_case_);
470465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&exit_);
470565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
470665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
470765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
470865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharFromCodeGenerator::GenerateSlow(
4709c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
4710c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    const RuntimeCallHelper& call_helper) {
4711594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
471265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
471365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow_case_);
471465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.BeforeCall(masm);
471565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(code_);
471665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CallRuntime(Runtime::kCharFromCode, 1);
471765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Move(result_, r0);
471865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.AfterCall(masm);
471965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&exit_);
472065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4721594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
472265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
472365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
472465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
472565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
472665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register dest,
472765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register src,
472865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register count,
472965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register scratch,
473065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          bool ascii) {
473165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label loop;
473265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label done;
473365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // This loop just copies one character at a time, as it is only used for very
473465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // short strings.
473565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!ascii) {
473665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ add(count, count, Operand(count), SetCC);
473765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
473859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(count, Operand::Zero());
473965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
474065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &done);
474165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
474265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
474365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(scratch, MemOperand(src, 1, PostIndex));
474465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Perform sub between load and dependent store to get the load time to
474565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // complete.
474665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(count, count, Operand(1), SetCC);
474765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ strb(scratch, MemOperand(dest, 1, PostIndex));
474865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // last iteration.
474965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(gt, &loop);
475065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
475165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
475265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
475365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
475465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
475565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgenum CopyCharactersFlags {
475665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  COPY_ASCII = 1,
475765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  DEST_ALWAYS_ALIGNED = 2
475865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
475965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
476065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
476165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
476265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register dest,
476365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register src,
476465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register count,
476565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch1,
476665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch2,
476765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch3,
476865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch4,
476965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              Register scratch5,
477065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                              int flags) {
477165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  bool ascii = (flags & COPY_ASCII) != 0;
477265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
477365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
477465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (dest_always_aligned && FLAG_debug_code) {
477565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check that destination is actually word aligned if the flag says
477665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // that it is.
477765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ tst(dest, Operand(kPointerAlignmentMask));
4778594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(eq, kDestinationOfCopyNotAligned);
477965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
478065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
478165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  const int kReadAlignment = 4;
478265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  const int kReadAlignmentMask = kReadAlignment - 1;
478365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Ensure that reading an entire aligned word containing the last character
478465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // of a string will not read outside the allocated area (because we pad up
478565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // to kObjectAlignment).
478665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kObjectAlignment >= kReadAlignment);
478765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Assumes word reads and writes are little endian.
478865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Nothing to do for zero characters.
478965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label done;
479065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!ascii) {
479165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ add(count, count, Operand(count), SetCC);
479265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
479359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(count, Operand::Zero());
479465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
479565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &done);
479665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
479765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Assume that you cannot read (or write) unaligned.
479865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label byte_loop;
479965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Must copy at least eight bytes, otherwise just do it one byte at a time.
480065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(count, Operand(8));
480165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(count, dest, Operand(count));
480265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register limit = count;  // Read until src equals this.
480365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(lt, &byte_loop);
480465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
480565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!dest_always_aligned) {
480665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Align dest by byte copying. Copies between zero and three bytes.
480765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ and_(scratch4, dest, Operand(kReadAlignmentMask), SetCC);
480865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label dest_aligned;
480965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(eq, &dest_aligned);
481065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(scratch4, Operand(2));
481165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(scratch1, MemOperand(src, 1, PostIndex));
481265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(scratch2, MemOperand(src, 1, PostIndex), le);
481365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(scratch3, MemOperand(src, 1, PostIndex), lt);
481465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ strb(scratch1, MemOperand(dest, 1, PostIndex));
481565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ strb(scratch2, MemOperand(dest, 1, PostIndex), le);
481665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ strb(scratch3, MemOperand(dest, 1, PostIndex), lt);
481765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&dest_aligned);
481865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
481965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
482065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label simple_loop;
482165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
482265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(scratch4, dest, Operand(src));
482365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(scratch4, scratch4, Operand(0x03), SetCC);
482465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &simple_loop);
482565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Shift register is number of bits in a source word that
482665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // must be combined with bits in the next source word in order
482765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // to create a destination word.
482865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
482965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Complex loop for src/dst that are not aligned the same way.
483065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  {
483165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label loop;
483265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(scratch4, Operand(scratch4, LSL, 3));
483365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Register left_shift = scratch4;
483465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ and_(src, src, Operand(~3));  // Round down to load previous word.
483565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(scratch1, MemOperand(src, 4, PostIndex));
483665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Store the "shift" most significant bits of scratch in the least
483765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // signficant bits (i.e., shift down by (32-shift)).
483865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ rsb(scratch2, left_shift, Operand(32));
483965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Register right_shift = scratch2;
484065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(scratch1, Operand(scratch1, LSR, right_shift));
484165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
484265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&loop);
484365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(scratch3, MemOperand(src, 4, PostIndex));
484465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ sub(scratch5, limit, Operand(dest));
484565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift));
484665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ str(scratch1, MemOperand(dest, 4, PostIndex));
484765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(scratch1, Operand(scratch3, LSR, right_shift));
484865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Loop if four or more bytes left to copy.
484965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Compare to eight, because we did the subtract before increasing dst.
485065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ sub(scratch5, scratch5, Operand(8), SetCC);
485165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ge, &loop);
485265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
485365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // There is now between zero and three bytes left to copy (negative that
485465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // number is in scratch5), and between one and three bytes already read into
485565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // scratch1 (eight times that number in scratch4). We may have read past
485665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // the end of the string, but because objects are aligned, we have not read
485765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // past the end of the object.
485865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Find the minimum of remaining characters to move and preloaded characters
485965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // and write those as bytes.
486065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(scratch5, scratch5, Operand(4), SetCC);
486165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &done);
486265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(scratch4, Operand(scratch5, LSL, 3), ne);
486365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Move minimum of bytes read and bytes left to copy to scratch4.
486465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch5, Operand(scratch4, LSR, 3), LeaveCC, lt);
486565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Between one and three (value in scratch5) characters already read into
486665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // scratch ready to write.
486765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(scratch5, Operand(2));
486865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ strb(scratch1, MemOperand(dest, 1, PostIndex));
486965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge);
487065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge);
487165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, gt);
487265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ strb(scratch1, MemOperand(dest, 1, PostIndex), gt);
487365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy any remaining bytes.
487465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(&byte_loop);
487565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
487665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Simple loop.
487765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy words from src to dst, until less than four bytes left.
487865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Both src and dest are word aligned.
487965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&simple_loop);
488065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  {
488165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label loop;
488265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&loop);
488365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(scratch1, MemOperand(src, 4, PostIndex));
488465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ sub(scratch3, limit, Operand(dest));
488565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ str(scratch1, MemOperand(dest, 4, PostIndex));
488665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Compare to 8, not 4, because we do the substraction before increasing
488765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // dest.
488865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(scratch3, Operand(8));
488965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ge, &loop);
489065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
489165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
489265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy bytes from src to dst until dst hits limit.
489365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&byte_loop);
489465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(dest, Operand(limit));
489565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt);
489665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ge, &done);
489765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ strb(scratch1, MemOperand(dest, 1, PostIndex));
489865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(&byte_loop);
489965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
490065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
490165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
490265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
490365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
49044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
490565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register c1,
490665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register c2,
490765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch1,
490865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch2,
490965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch3,
491065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch4,
491165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch5,
491265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Label* not_found) {
491365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Register scratch3 is the general scratch register in this function.
491465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register scratch = scratch3;
491565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
491665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make sure that both characters are not digits as such strings has a
49174a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // different hash algorithm. Don't try to look for these in the string table.
491865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label not_array_index;
491965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(scratch, c1, Operand(static_cast<int>('0')));
492065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
492165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(hi, &not_array_index);
492265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(scratch, c2, Operand(static_cast<int>('0')));
492365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
492465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
492565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If check failed combine both characters into single halfword.
492665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // This is required by the contract of the method: code at the
492765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // not_found branch expects this combination in c1 register
492865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls);
492965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ls, not_found);
493065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
493165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_array_index);
493265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate the two character string hash.
493365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register hash = scratch1;
493465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateHashInit(masm, hash, c1);
493565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateHashAddCharacter(masm, hash, c2);
493665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateHashGetHash(masm, hash);
493765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
493865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Collect the two characters in a register.
493965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register chars = c1;
494065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte));
494165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
494265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
494365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash:  hash of two character string.
494465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
49454a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Load string table
49464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Load address of first element of the string table.
49474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register string_table = c2;
49484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadRoot(string_table, Heap::kStringTableRootIndex);
494965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
495065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register undefined = scratch4;
495165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
495265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
49534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Calculate capacity mask from the string table capacity.
495465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register mask = scratch2;
49554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldr(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset));
495665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(mask, Operand(mask, ASR, 1));
495765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(mask, mask, Operand(1));
495865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
49594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Calculate untagged address of the first element of the string table.
49604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register first_string_table_element = string_table;
49614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ add(first_string_table_element, string_table,
49624a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org         Operand(StringTable::kElementsStartOffset - kHeapObjectTag));
496365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
496465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Registers
496565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
496665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash:  hash of two character string
496765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // mask:  capacity mask
49684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // first_string_table_element: address of the first element of
49694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  //                             the string table
4970badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // undefined: the undefined object
497165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // scratch: -
497265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
49734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Perform a number of probes in the string table.
49741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kProbes = 4;
49754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label found_in_string_table;
497665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label next_probe[kProbes];
49772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  Register candidate = scratch5;  // Scratch register contains candidate.
497865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  for (int i = 0; i < kProbes; i++) {
49794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Calculate entry in string table.
498065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (i > 0) {
49814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ add(candidate, hash, Operand(StringTable::GetProbeOffset(i)));
498265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    } else {
498365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ mov(candidate, hash);
498465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
498565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
498665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ and_(candidate, candidate, Operand(mask));
498765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
498865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Load the entry from the symble table.
49894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    STATIC_ASSERT(StringTable::kEntrySize == 1);
499065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(candidate,
49914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org           MemOperand(first_string_table_element,
499265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      candidate,
499365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      LSL,
499465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      kPointerSizeLog2));
499565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
499665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If entry is undefined no string with this hash can be found.
4997badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    Label is_string;
4998badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE);
4999badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ b(ne, &is_string);
5000badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
5001badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ cmp(undefined, candidate);
500265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(eq, not_found);
50032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    // Must be the hole (deleted entry).
5004badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    if (FLAG_debug_code) {
50052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org      __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
5006badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org      __ cmp(ip, candidate);
5007594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole);
5008badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    }
5009badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ jmp(&next_probe[i]);
5010badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
5011badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ bind(&is_string);
5012badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
5013badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    // Check that the candidate is a non-external ASCII string.  The instance
5014badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    // type is still in the scratch register from the CompareObjectType
5015badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    // operation.
5016badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]);
501765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
501865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If length is not 2 the string is not a candidate.
501965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset));
502065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(scratch, Operand(Smi::FromInt(2)));
502165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ne, &next_probe[i]);
502265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
502365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check if the two characters match.
502465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Assumes that word load is little endian.
5025fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize));
502665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(chars, scratch);
50274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ b(eq, &found_in_string_table);
502865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&next_probe[i]);
502965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
503065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
503165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // No matching 2 character string found by probing.
503265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(not_found);
503365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
503465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Scratch register contains result when we fall through to here.
50352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  Register result = candidate;
50364a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&found_in_string_table);
503765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Move(r0, result);
503865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
503965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
504065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
504165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashInit(MacroAssembler* masm,
504265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register hash,
504365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register character) {
504465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash = character + (character << 10);
5045f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ LoadRoot(hash, Heap::kHashSeedRootIndex);
5046fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // Untag smi seed and add the character.
5047fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  __ add(hash, character, Operand(hash, LSR, kSmiTagSize));
5048fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // hash += hash << 10;
5049fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  __ add(hash, hash, Operand(hash, LSL, 10));
505065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash ^= hash >> 6;
50512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  __ eor(hash, hash, Operand(hash, LSR, 6));
505265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
505365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
505465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
505565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
505665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                            Register hash,
505765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                            Register character) {
505865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += character;
505965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(hash, hash, Operand(character));
506065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += hash << 10;
506165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(hash, hash, Operand(hash, LSL, 10));
506265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash ^= hash >> 6;
50632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  __ eor(hash, hash, Operand(hash, LSR, 6));
506465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
506565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
506665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
506765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashGetHash(MacroAssembler* masm,
506865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register hash) {
506965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += hash << 3;
507065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(hash, hash, Operand(hash, LSL, 3));
507165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash ^= hash >> 11;
50722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  __ eor(hash, hash, Operand(hash, LSR, 11));
507365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += hash << 15;
5074f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ add(hash, hash, Operand(hash, LSL, 15));
507565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
5076f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ and_(hash, hash, Operand(String::kHashBitMask), SetCC);
50772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
507865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // if (hash == 0) hash = 27;
5079f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ mov(hash, Operand(StringHasher::kZeroHash), LeaveCC, eq);
508065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
508165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
508265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
508365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid SubStringStub::Generate(MacroAssembler* masm) {
508465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime;
508565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
508665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack frame on entry.
508765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  lr: return address
508865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[0]: to
508965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[4]: from
509065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[8]: string
509165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
509265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // This stub is called from the native-call %_SubString(...), so
509365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // nothing can be assumed about the arguments. It is tested that:
509465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  "string" is a sequential string,
509565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  both "from" and "to" are smis, and
509665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  0 <= from <= to <= string.length.
509765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If any of these assumptions fail, we call the runtime system.
509865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
50991456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kToOffset = 0 * kPointerSize;
51001456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kFromOffset = 1 * kPointerSize;
51011456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  const int kStringOffset = 2 * kPointerSize;
510265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
51037ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ Ldrd(r2, r3, MemOperand(sp, kToOffset));
5104d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  STATIC_ASSERT(kFromOffset == kToOffset + 4);
510565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
510665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
51074668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
5108e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // Arithmetic shift right by one un-smi-tags. In this case we rotate right
5109e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // instead because we bail out on non-smi values: ROR and ASR are equivalent
5110e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // for smis but they set the flags in a way that's easier to optimize.
5111e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ mov(r2, Operand(r2, ROR, 1), SetCC);
5112e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ mov(r3, Operand(r3, ROR, 1), SetCC, cc);
5113e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // If either to or from had the smi tag bit set, then C is set now, and N
5114e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // has the same value: we rotated by 1, so the bottom bit is now the top bit.
5115fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // We want to bailout to runtime here if From is negative.  In that case, the
5116fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // next instruction is not executed and we fall through to bailing out to
5117e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // runtime.
5118e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // Executed if both r2 and r3 are untagged integers.
5119e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ sub(r2, r2, Operand(r3), SetCC, cc);
5120e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // One of the above un-smis or the above SUB could have set N==1.
5121e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ b(mi, &runtime);  // Either "from" or "to" is not an smi, or from > to.
512265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
51237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Make sure first argument is a string.
51241805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ ldr(r0, MemOperand(sp, kStringOffset));
5125e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  // Do a JumpIfSmi, but fold its jump into the subsequent string test.
5126bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiTst(r0);
5127e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  Condition is_string = masm->IsObjectStringType(r0, r1, ne);
5128e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  ASSERT(is_string == eq);
512965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(NegateCondition(is_string), &runtime);
513065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
51312e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  Label single_char;
51322e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ cmp(r2, Operand(1));
51332e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ b(eq, &single_char);
51342e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org
51351805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // Short-cut for the case of trivial substring.
51361805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  Label return_r0;
51371805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r0: original string
51381805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r2: result string length
51391805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset));
51401805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ cmp(r2, Operand(r4, ASR, 1));
5141ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Return original string.
51421805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ b(eq, &return_r0);
5143ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Longer than original string's length or negative: unsafe arguments.
5144ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  __ b(hi, &runtime);
5145ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Shorter than original string's length: an actual substring.
51461805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
51477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Deal with different string types: update the index if necessary
51487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // and put the underlying string into r5.
51497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r0: original string
51507ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r1: instance type
51517ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r2: length
51527ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r3: from index (untagged)
51537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label underlying_unpacked, sliced_string, seq_or_external_string;
51547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // If the string is not indirect, it can only be sequential or external.
51557ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
51567ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kIsIndirectStringMask != 0);
51577ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r1, Operand(kIsIndirectStringMask));
51587ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(eq, &seq_or_external_string);
51597ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
51607ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r1, Operand(kSlicedNotConsMask));
51617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(ne, &sliced_string);
51627ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Cons string.  Check whether it is flat, then fetch first part.
51637ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset));
51644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ CompareRoot(r5, Heap::kempty_stringRootIndex);
51657ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(ne, &runtime);
51667ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset));
51677ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Update instance type.
51687ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset));
51697ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
51707ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ jmp(&underlying_unpacked);
51717ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
51727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&sliced_string);
51737ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Sliced string.  Fetch parent and correct start index by offset.
51747ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
5175bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset));
5176fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ add(r3, r3, Operand(r4, ASR, 1));  // Add offset to index.
51777ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Update instance type.
51787ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset));
51797ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
51807ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ jmp(&underlying_unpacked);
51817ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
51827ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&seq_or_external_string);
51837ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Sequential or external string.  Just move string to the expected register.
51847ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(r5, r0);
51857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
51867ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&underlying_unpacked);
518765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
51887ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  if (FLAG_string_slices) {
51897ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    Label copy_routine;
51907ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // r5: underlying subject string
51917ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // r1: instance type of underlying subject string
51927ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // r2: length
51937ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // r3: adjusted start index (untagged)
51947ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ cmp(r2, Operand(SlicedString::kMinLength));
51957ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // Short slice.  Copy instead of slicing.
51967ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ b(lt, &copy_routine);
51977ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // Allocate new sliced string.  At this point we do not reload the instance
51987ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // type including the string encoding because we simply rely on the info
51997ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // provided by the original string.  It does not matter if the original
52007ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // string's encoding is wrong because we always have to recheck encoding of
52017ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // the newly created string's parent anyways due to externalized strings.
52027ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    Label two_byte_slice, set_slice_header;
5203e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
52047ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
52057ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ tst(r1, Operand(kStringEncodingMask));
52067ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ b(eq, &two_byte_slice);
52077ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ AllocateAsciiSlicedString(r0, r2, r6, r7, &runtime);
52087ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ jmp(&set_slice_header);
52097ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ bind(&two_byte_slice);
52107ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime);
52117ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ bind(&set_slice_header);
52127ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ mov(r3, Operand(r3, LSL, 1));
52137ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
5214bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset));
52157ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ jmp(&return_r0);
52161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
52177ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ bind(&copy_routine);
52187ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  }
521965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
52207ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r5: underlying subject string
52217ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r1: instance type of underlying subject string
52227ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r2: length
52237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r3: adjusted start index (untagged)
52247ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label two_byte_sequential, sequential_string, allocate_result;
52257ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kExternalStringTag != 0);
52267ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
52277ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r1, Operand(kExternalStringTag));
52287ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(eq, &sequential_string);
52297ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
52307ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Handle external string.
52317ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Rule out short external strings.
52327ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_CHECK(kShortExternalStringTag != 0);
52337ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r1, Operand(kShortExternalStringTag));
52347ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(ne, &runtime);
52357ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset));
52367ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r5 already points to the first character of underlying string.
52377ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ jmp(&allocate_result);
52387ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
52397ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&sequential_string);
52407ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Locate first character of underlying subject string.
5241fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
5242fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
52437ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
52447ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&allocate_result);
52457ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Sequential acii string.  Allocate the result.
5246e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
52477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r1, Operand(kStringEncodingMask));
52487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(eq, &two_byte_sequential);
52497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
52502efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Allocate and copy the resulting ASCII string.
52517ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime);
52527ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
52537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Locate first character of substring to copy.
52547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ add(r5, r5, r3);
525565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate first character of result.
5256fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
525765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
52581805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r0: result string
52591805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r1: first character of result string
52601805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r2: result string length
52611805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r5: first character of substring to copy
5262fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
526365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
526465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           COPY_ASCII | DEST_ALWAYS_ALIGNED);
52651805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ jmp(&return_r0);
526665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
52677ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Allocate and copy the resulting two-byte string.
52687ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&two_byte_sequential);
52697ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime);
527065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
52717ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Locate first character of substring to copy.
52721805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
52737ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ add(r5, r5, Operand(r3, LSL, 1));
527465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate first character of result.
527565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
52761805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
527765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: result string.
527865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: first character of result.
527965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: result length.
52801805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // r5: first character of substring to copy.
528165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
5282d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  StringHelper::GenerateCopyCharactersLong(
5283d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
52841805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
52851805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ bind(&return_r0);
52867ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Counters* counters = masm->isolate()->counters();
52877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->sub_string_native(), 1, r3, r4);
52882e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ Drop(3);
528965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
529065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
529165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Just jump to runtime to create the sub string.
529265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
529365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kSubString, 3, 1);
52942e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org
52952e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ bind(&single_char);
52962e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // r0: original string
52972e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // r1: instance type
52982e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // r2: length
52992e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // r3: from index (untagged)
53002e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ SmiTag(r3, r3);
53012e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  StringCharAtGenerator generator(
53022e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org      r0, r3, r2, r0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
53032e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  generator.GenerateFast(masm);
53042e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ Drop(3);
53052e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ Ret();
53062e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  generator.SkipSlow(masm, &runtime);
530765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
530865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
530965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
53101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
53111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register left,
53121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register right,
53131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register scratch1,
53141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register scratch2,
53151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register scratch3) {
53161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register length = scratch1;
53171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
53181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare lengths.
53191c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label strings_not_equal, check_zero_length;
53201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldr(length, FieldMemOperand(left, String::kLengthOffset));
53211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
53221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ cmp(length, scratch2);
53231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(eq, &check_zero_length);
53241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&strings_not_equal);
53251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(r0, Operand(Smi::FromInt(NOT_EQUAL)));
53261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Ret();
53271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
53281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check if the length is zero.
53291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label compare_chars;
53301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&check_zero_length);
53311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kSmiTag == 0);
533259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(length, Operand::Zero());
53331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(ne, &compare_chars);
53341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(r0, Operand(Smi::FromInt(EQUAL)));
53351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Ret();
53361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
53371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare characters.
53381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&compare_chars);
53391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  GenerateAsciiCharsCompareLoop(masm,
53401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                left, right, length, scratch2, scratch3,
53411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                &strings_not_equal);
53421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
53431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Characters are equal.
53441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(r0, Operand(Smi::FromInt(EQUAL)));
53451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Ret();
53461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
53471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
53481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
534965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
535065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register left,
535165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register right,
535265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch1,
535365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch2,
535465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch3,
535565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch4) {
53561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label result_not_equal, compare_lengths;
535765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Find minimum length and length difference.
535865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset));
535965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
536065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(scratch3, scratch1, Operand(scratch2), SetCC);
536165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register length_delta = scratch3;
536265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch1, scratch2, LeaveCC, gt);
536365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register min_length = scratch1;
536465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
536559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(min_length, Operand::Zero());
536665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &compare_lengths);
536765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
53681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare loop.
53691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  GenerateAsciiCharsCompareLoop(masm,
53701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                left, right, min_length, scratch2, scratch4,
53711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                &result_not_equal);
537265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
53731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare lengths - strings up to min-length are equal.
537465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&compare_lengths);
537565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
53761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Use length_delta as result if it's zero.
53771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(r0, Operand(length_delta), SetCC);
53781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&result_not_equal);
53791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Conditionally update the result based either on length_delta or
53801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // the last comparion performed in the loop above.
538165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt);
538265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt);
538365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
538465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
538565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
538665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
53871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid StringCompareStub::GenerateAsciiCharsCompareLoop(
53881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    MacroAssembler* masm,
53891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register left,
53901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register right,
53911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register length,
53921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register scratch1,
53931c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register scratch2,
53941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Label* chars_not_equal) {
53951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Change index to run from -length to -1 by adding length to string
53961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // start. This means that loop ends when index reaches zero, which
53971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // doesn't need an additional compare.
53981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ SmiUntag(length);
53991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ add(scratch1, length,
5400fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
54011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ add(left, left, Operand(scratch1));
54021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ add(right, right, Operand(scratch1));
5403ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org  __ rsb(length, length, Operand::Zero());
54041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register index = length;  // index = -length;
54051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
54061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare loop.
54071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label loop;
54081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&loop);
54091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldrb(scratch1, MemOperand(left, index));
54101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldrb(scratch2, MemOperand(right, index));
54111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ cmp(scratch1, scratch2);
54121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(ne, chars_not_equal);
54131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ add(index, index, Operand(1), SetCC);
54141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(ne, &loop);
54151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
54161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
54171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
541865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCompareStub::Generate(MacroAssembler* masm) {
541965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime;
542065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
54217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
54227979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
542365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack frame on entry.
542465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[0]: right string
542565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  sp[4]: left string
5426d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  __ Ldrd(r0 , r1, MemOperand(sp));  // Load right in r0, left in r1.
542765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
542865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label not_same;
542965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r0, r1);
543065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &not_same);
543165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(EQUAL == 0);
543265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
543365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(Smi::FromInt(EQUAL)));
54347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_compare_native(), 1, r1, r2);
543565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
543665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
543765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
543865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_same);
543965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
5440badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Check that both objects are sequential ASCII strings.
5441d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime);
544265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
5443badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Compare flat ASCII strings natively. Remove arguments from stack first.
54447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_compare_native(), 1, r2, r3);
544565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
5446d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5);
544765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
544865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
544965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // tagged as a small integer.
545065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
545165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
545265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
545365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
545465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
545565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringAddStub::Generate(MacroAssembler* masm) {
54567ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label call_runtime, call_builtin;
54573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  Builtins::JavaScript builtin_id = Builtins::ADD;
54583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
54597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
54607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
546165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack on entry:
54623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // sp[0]: second argument (right).
54633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // sp[4]: first argument (left).
546465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
546565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load the two arguments.
546665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r0, MemOperand(sp, 1 * kPointerSize));  // First argument.
546765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ldr(r1, MemOperand(sp, 0 * kPointerSize));  // Second argument.
546865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
546965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make sure that both arguments are strings if not known in advance.
5470ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Otherwise, at least one of the arguments is definitely a string,
5471ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // and we convert the one that is not known to be a string.
5472ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
5473ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
5474ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
54757ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ JumpIfEitherSmi(r0, r1, &call_runtime);
547665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Load instance types.
547765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
547865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
547965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
548065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
548165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kStringTag == 0);
548265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If either is not a string, go to runtime.
548365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ tst(r4, Operand(kIsNotStringMask));
548465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ tst(r5, Operand(kIsNotStringMask), eq);
54857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ b(ne, &call_runtime);
5486ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
5487ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
5488ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    GenerateConvertArgument(
5489ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org        masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin);
5490ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    builtin_id = Builtins::STRING_ADD_RIGHT;
5491ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
5492ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
5493ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    GenerateConvertArgument(
5494ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org        masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin);
5495ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    builtin_id = Builtins::STRING_ADD_LEFT;
549665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
549765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
549865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Both arguments are strings.
549965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: first string
550065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: second string
55013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
55023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
550365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  {
550465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label strings_not_empty;
550565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check if either of the strings are empty. In that case return the other.
550665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset));
550765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset));
550865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kSmiTag == 0);
550965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(r2, Operand(Smi::FromInt(0)));  // Test if first string is empty.
551065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(r0, Operand(r1), LeaveCC, eq);  // If first is empty, return second.
551165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kSmiTag == 0);
551265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org     // Else test if second string is empty.
551365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(r3, Operand(Smi::FromInt(0)), ne);
551465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ b(ne, &strings_not_empty);  // If either string was empty, return r0.
551565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
55167979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
551765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ add(sp, sp, Operand(2 * kPointerSize));
551865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Ret();
551965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
552065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&strings_not_empty);
552165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
552265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
5523bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r2);
5524bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(r3);
552565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Both strings are non-empty.
552665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: first string
552765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: second string
552865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: length of first string
552965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: length of second string
55303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
55313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
553265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Look at the length of the result of adding the two strings.
553365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label string_add_flat_result, longer_than_two;
553465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Adding two lengths can't overflow.
553565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
553665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(r6, r2, Operand(r3));
55374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Use the string table when adding two one character strings, as it
55384a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // helps later optimizations to return a string here.
553965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r6, Operand(2));
554065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &longer_than_two);
554165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
5542badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // Check that both strings are non-external ASCII strings.
5543ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
554465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
554565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
554665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
554765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
554865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
554965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
55507ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org                                                  &call_runtime);
555165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
555265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the two characters forming the sub string.
5553fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
5554fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize));
555565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
55564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Try to lookup two character string in string table. If it is not found
555765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // just allocate a new one.
555865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label make_two_character_string;
55594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  StringHelper::GenerateTwoCharacterStringTableProbe(
556065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
55617979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
556265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
556365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
556465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
556565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&make_two_character_string);
556665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Resulting string has length 2 and first chars of two strings
556765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // are combined into single halfword in r2 register.
556865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // So we can fill resulting string without two loops by a single
556965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // halfword store instruction (which assumes that processor is
557065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // in a little endian mode)
557165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r6, Operand(2));
55727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime);
5573fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ strh(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize));
55747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
557565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
557665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
557765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
557865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&longer_than_two);
557965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if resulting string will be flat.
55802efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  __ cmp(r6, Operand(ConsString::kMinLength));
558165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(lt, &string_add_flat_result);
558265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle exceptionally long strings in the runtime system.
558365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
558465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(IsPowerOf2(String::kMaxLength + 1));
558565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
558665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(r6, Operand(String::kMaxLength + 1));
55877ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(hs, &call_runtime);
558865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
558965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If result is not supposed to be flat, allocate a cons string object.
5590badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  // If both strings are ASCII the result is an ASCII cons string.
5591ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
559265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
559365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
559465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
559565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
559665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
559765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label non_ascii, allocated, ascii_data;
559865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kTwoByteStringTag == 0);
559965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r4, Operand(kStringEncodingMask));
560065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r5, Operand(kStringEncodingMask), ne);
560165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &non_ascii);
560265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
560365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Allocate an ASCII cons string.
560465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&ascii_data);
56057ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime);
560665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&allocated);
560765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fill the fields of the cons string.
560857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Label skip_write_barrier, after_writing;
560957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  ExternalReference high_promotion_mode = ExternalReference::
561057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      new_space_high_promotion_mode_active_address(masm->isolate());
561157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ mov(r4, Operand(high_promotion_mode));
561257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ ldr(r4, MemOperand(r4, 0));
561357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ cmp(r4, Operand::Zero());
561457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ b(eq, &skip_write_barrier);
561557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
561665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
561757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ RecordWriteField(r7,
561857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      ConsString::kFirstOffset,
561957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      r0,
562057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      r4,
562157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      kLRHasNotBeenSaved,
562257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      kDontSaveFPRegs);
562365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
562457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ RecordWriteField(r7,
562557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      ConsString::kSecondOffset,
562657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      r1,
562757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      r4,
562857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      kLRHasNotBeenSaved,
562957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      kDontSaveFPRegs);
563057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ jmp(&after_writing);
563157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
563257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ bind(&skip_write_barrier);
563357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
563457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
563557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
563657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ bind(&after_writing);
563757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
563865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(r0, Operand(r7));
56397979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
564065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
564165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
564265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
564365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&non_ascii);
564465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // At least one of the strings is two-byte. Check whether it happens
5645ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // to contain only one byte characters.
564665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r4: first instance type.
564765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r5: second instance type.
5648ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ tst(r4, Operand(kOneByteDataHintMask));
5649ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ tst(r5, Operand(kOneByteDataHintMask), ne);
565065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(ne, &ascii_data);
565146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ eor(r4, r4, Operand(r5));
5652ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
5653ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ and_(r4, r4, Operand(kOneByteStringTag | kOneByteDataHintTag));
5654ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ cmp(r4, Operand(kOneByteStringTag | kOneByteDataHintTag));
565546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ b(eq, &ascii_data);
565665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
565765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Allocate a two byte cons string.
56587ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime);
565965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&allocated);
566065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
56617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // We cannot encounter sliced strings or cons strings here since:
56622efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
56637ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Handle creating a flat result from either external or sequential strings.
56647ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Locate the first characters' locations.
566565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r0: first string
566665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r1: second string
566765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: length of first string
566865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: length of second string
56693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
56703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
567165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r6: sum of lengths.
56727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label first_prepared, second_prepared;
567365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&string_add_flat_result);
5674ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) {
567565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
567665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
567765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
567865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
567965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
56807ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
56817ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Check whether both strings have same encoding
56827ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ eor(r7, r4, Operand(r5));
56837ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r7, Operand(kStringEncodingMask));
56847ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(ne, &call_runtime);
56857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
568665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
568765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ tst(r4, Operand(kStringRepresentationMask));
5688fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
56897ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ add(r7,
56907ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org         r0,
5691fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
56927ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org         LeaveCC,
56937ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org         eq);
56947ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(eq, &first_prepared);
56957ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // External string: rule out short external string and load string resource.
56967ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kShortExternalStringTag != 0);
56977ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r4, Operand(kShortExternalStringMask));
56987ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(ne, &call_runtime);
56997ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
57007ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&first_prepared);
57017ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
57027ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
57037ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r5, Operand(kStringRepresentationMask));
5704fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
57057ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ add(r1,
57067ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org         r1,
5707fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
57087ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org         LeaveCC,
57097ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org         eq);
57107ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(eq, &second_prepared);
57117ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // External string: rule out short external string and load string resource.
57127ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kShortExternalStringTag != 0);
57137ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r5, Operand(kShortExternalStringMask));
57147ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ b(ne, &call_runtime);
57157ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset));
57167ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&second_prepared);
57177ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
57187ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label non_ascii_string_add_flat_result;
57197ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r7: first character of first string
57207ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r1: first character of second string
572165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: length of first string.
572265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: length of second string.
57237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r6: sum of lengths.
57247ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Both strings have the same encoding.
57257ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kTwoByteStringTag == 0);
57267ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ tst(r5, Operand(kStringEncodingMask));
572765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ b(eq, &non_ascii_string_add_flat_result);
572865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
57297ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime);
5730fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(r6, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
57317ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r0: result string.
57327ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r7: first character of first string.
57337ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r1: first character of second string.
573465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: length of first string.
573565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: length of second string.
573665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r6: first character of result.
57377ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true);
573865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r6: next character of result.
573965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true);
57407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
574165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
574265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
574365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
574465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&non_ascii_string_add_flat_result);
57457ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime);
57467ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
57477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r0: result string.
57487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r7: first character of first string.
57497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r1: first character of second string.
575065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r2: length of first string.
575165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r3: length of second string.
575265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // r6: first character of result.
57537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false);
57547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // r6: next character of result.
575565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
57567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
575765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ add(sp, sp, Operand(2 * kPointerSize));
575865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Ret();
575965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
576065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Just jump to runtime to add the two strings.
57617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&call_runtime);
5762ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) {
57634e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    GenerateRegisterArgsPop(masm);
57644e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    // Build a frame
57654e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    {
57664e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      FrameScope scope(masm, StackFrame::INTERNAL);
57674e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      GenerateRegisterArgsPush(masm);
57684e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ CallRuntime(Runtime::kStringAdd, 2);
57694e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    }
57704e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    __ Ret();
57714e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  } else {
57724e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
57734e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  }
57743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
57753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  if (call_builtin.is_linked()) {
57763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org    __ bind(&call_builtin);
5777ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) {
57784e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      GenerateRegisterArgsPop(masm);
57794e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      // Build a frame
57804e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      {
57814e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org        FrameScope scope(masm, StackFrame::INTERNAL);
57824e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org        GenerateRegisterArgsPush(masm);
57834e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org        __ InvokeBuiltin(builtin_id, CALL_FUNCTION);
57844e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      }
57854e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ Ret();
57864e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    } else {
57874e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
57884e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    }
57893a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  }
57903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org}
57913a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
57923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
57934e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgvoid StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
57944e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ push(r0);
57954e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ push(r1);
57964e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
57974e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
57984e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
57994e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgvoid StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm) {
58004e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ pop(r1);
58014e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ pop(r0);
58024e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
58034e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
58044e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
58053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
58063a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            int stack_offset,
58073a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            Register arg,
58083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            Register scratch1,
58093a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            Register scratch2,
58103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            Register scratch3,
58113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            Register scratch4,
58123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                            Label* slow) {
58133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // First check if the argument is already a string.
58143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  Label not_string, done;
58153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ JumpIfSmi(arg, &not_string);
58163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ CompareObjectType(arg, scratch1, scratch1, FIRST_NONSTRING_TYPE);
58173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ b(lt, &done);
58183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
58193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Check the number to string cache.
58203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  Label not_cached;
58213a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ bind(&not_string);
58223a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Puts the cached result into scratch1.
58233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  NumberToStringStub::GenerateLookupNumberStringCache(masm,
58243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                                      arg,
58253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                                      scratch1,
58263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                                      scratch2,
58273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                                      scratch3,
58283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                                      scratch4,
58293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org                                                      &not_cached);
58303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ mov(arg, scratch1);
58313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ str(arg, MemOperand(sp, stack_offset));
58323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ jmp(&done);
58333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
58343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  // Check if the argument is a safe string wrapper.
58353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ bind(&not_cached);
58363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ JumpIfSmi(arg, slow);
58373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ CompareObjectType(
58383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      arg, scratch1, scratch2, JS_VALUE_TYPE);  // map -> scratch1.
58393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ b(ne, slow);
58403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset));
58413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ and_(scratch2,
58423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org          scratch2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
58433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ cmp(scratch2,
58443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org         Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
58453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ b(ne, slow);
58463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ ldr(arg, FieldMemOperand(arg, JSValue::kValueOffset));
58473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ str(arg, MemOperand(sp, stack_offset));
58483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org
58493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org  __ bind(&done);
585065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
585165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
585265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
5853a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid ICCompareStub::GenerateSmis(MacroAssembler* masm) {
5854fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(state_ == CompareIC::SMI);
5855a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label miss;
5856a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ orr(r2, r1, r0);
58577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(r2, &miss);
5858a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5859a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  if (GetCondition() == eq) {
5860a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // For equality we do not care about the sign of the result.
5861a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ sub(r0, r0, r1, SetCC);
5862a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  } else {
5863496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    // Untag before subtracting to avoid handling overflow.
5864496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    __ SmiUntag(r1);
5865bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org    __ sub(r0, r1, Operand::SmiUntag(r0));
5866a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
5867a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Ret();
5868a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5869a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
5870a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GenerateMiss(masm);
5871a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
5872a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5873a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
58748432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
58758432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  ASSERT(state_ == CompareIC::NUMBER);
5876a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5877a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label generic_stub;
58789a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  Label unordered, maybe_undefined1, maybe_undefined2;
5879a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label miss;
5880a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5881fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (left_ == CompareIC::SMI) {
5882fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(r1, &miss);
5883fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
5884fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (right_ == CompareIC::SMI) {
5885fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(r0, &miss);
5886fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
5887a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5888a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Inlining the double comparison and falling back to the general compare
5889e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // stub if NaN is involved.
5890e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Load left and right operand.
5891e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Label done, left, left_smi, right_smi;
5892e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ JumpIfSmi(r0, &right_smi);
5893e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
5894e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org              DONT_DO_SMI_CHECK);
5895e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(r2, r0, Operand(kHeapObjectTag));
5896e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldr(d1, r2, HeapNumber::kValueOffset);
5897e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ b(&left);
5898e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&right_smi);
5899bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiToDouble(d1, r0);
5900e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
5901e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&left);
5902e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ JumpIfSmi(r1, &left_smi);
5903e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ CheckMap(r1, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
5904e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org              DONT_DO_SMI_CHECK);
5905e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(r2, r1, Operand(kHeapObjectTag));
5906e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vldr(d0, r2, HeapNumber::kValueOffset);
5907e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ b(&done);
5908e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&left_smi);
5909bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiToDouble(d0, r1);
5910a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5911e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ bind(&done);
5912e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Compare operands.
5913e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ VFPCompareAndSetFlags(d0, d1);
5914a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5915e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Don't base result on status bits when a NaN is involved.
5916e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ b(vs, &unordered);
5917a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5918e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Return a result of -1, 0, or 1, based on status bits.
5919e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r0, Operand(EQUAL), LeaveCC, eq);
5920e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r0, Operand(LESS), LeaveCC, lt);
5921e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ mov(r0, Operand(GREATER), LeaveCC, gt);
5922e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ Ret();
5923a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
59249a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  __ bind(&unordered);
5925a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&generic_stub);
5926fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ICCompareStub stub(op_, CompareIC::GENERIC, CompareIC::GENERIC,
5927fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                     CompareIC::GENERIC);
59288432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
5929a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
59309a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  __ bind(&maybe_undefined1);
59319a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  if (Token::IsOrderedRelationalCompareOp(op_)) {
59329a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
59339a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ b(ne, &miss);
5934fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(r1, &unordered);
59359a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
59369a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ b(ne, &maybe_undefined2);
59379a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ jmp(&unordered);
59389a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  }
59399a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
59409a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  __ bind(&maybe_undefined2);
59419a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  if (Token::IsOrderedRelationalCompareOp(op_)) {
59429a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ CompareRoot(r1, Heap::kUndefinedValueRootIndex);
59439a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ b(eq, &unordered);
59449a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  }
59459a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
5946a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
5947a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GenerateMiss(masm);
5948a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
5949a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5950a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
59514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
59524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(state_ == CompareIC::INTERNALIZED_STRING);
595383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label miss;
595483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
595583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Registers containing left and right operands respectively.
595683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register left = r1;
595783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register right = r0;
595883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register tmp1 = r2;
595983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register tmp2 = r3;
596083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
596183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Check that both operands are heap objects.
596283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ JumpIfEitherSmi(left, right, &miss);
596383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
59644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both operands are internalized strings.
596583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
596683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
596783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
596883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
5969ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
5970ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ orr(tmp1, tmp1, Operand(tmp2));
5971ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ tst(tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
59721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ b(ne, &miss);
597383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
59744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Internalized strings are compared by identity.
59754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(left, right);
59764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Make sure r0 is non-zero. At this point input operands are
59774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // guaranteed to be non-zero.
59784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(right.is(r0));
59794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  STATIC_ASSERT(EQUAL == 0);
59804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
59814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
59824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ Ret();
59834a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
59844a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&miss);
59854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  GenerateMiss(masm);
59864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
59874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
59884a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
59894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) {
59904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(state_ == CompareIC::UNIQUE_NAME);
59914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(GetCondition() == eq);
59924a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label miss;
59934a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
59944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Registers containing left and right operands respectively.
59954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register left = r1;
59964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register right = r0;
59974a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register tmp1 = r2;
59984a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register tmp2 = r3;
59994a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
60004a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both operands are heap objects.
60014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ JumpIfEitherSmi(left, right, &miss);
60024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
60034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both operands are unique names. This leaves the instance
60044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // types loaded in tmp1 and tmp2.
60054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
60064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
60074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
60084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
60094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
60101510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ JumpIfNotUniqueName(tmp1, &miss);
60111510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ JumpIfNotUniqueName(tmp2, &miss);
60124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
60134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Unique names are compared by identity.
601483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ cmp(left, right);
601583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Make sure r0 is non-zero. At this point input operands are
601683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // guaranteed to be non-zero.
601783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(right.is(r0));
601883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  STATIC_ASSERT(EQUAL == 0);
601983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  STATIC_ASSERT(kSmiTag == 0);
602083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
602183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ Ret();
602283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
602383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ bind(&miss);
602483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  GenerateMiss(masm);
602583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
602683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
602783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
60281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid ICCompareStub::GenerateStrings(MacroAssembler* masm) {
6029fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(state_ == CompareIC::STRING);
60301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label miss;
60311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60324efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  bool equality = Token::IsEqualityOp(op_);
60334efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
60341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Registers containing left and right operands respectively.
60351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register left = r1;
60361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register right = r0;
60371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp1 = r2;
60381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp2 = r3;
60391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp3 = r4;
60401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp4 = r5;
60411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check that both operands are heap objects.
60431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ JumpIfEitherSmi(left, right, &miss);
60441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check that both operands are strings. This leaves the instance
60461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // types loaded in tmp1 and tmp2.
60471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
60481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
60491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
60501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
60511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
60521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ orr(tmp3, tmp1, tmp2);
60531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ tst(tmp3, Operand(kIsNotStringMask));
60541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(ne, &miss);
60551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Fast check for identical strings.
60571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ cmp(left, right);
60581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(EQUAL == 0);
60591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kSmiTag == 0);
60601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq);
60611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Ret(eq);
60621c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60631c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Handle not identical strings.
60641c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both strings are internalized strings. If they are, we're done
60661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // because we already know they are not identical. We know they are both
60671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // strings.
60684efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (equality) {
60694efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    ASSERT(GetCondition() == eq);
6070ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    STATIC_ASSERT(kInternalizedTag == 0);
6071ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ orr(tmp3, tmp1, Operand(tmp2));
6072ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ tst(tmp3, Operand(kIsNotInternalizedMask));
60734efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    // Make sure r0 is non-zero. At this point input operands are
60744efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    // guaranteed to be non-zero.
60754efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    ASSERT(right.is(r0));
6076ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ Ret(eq);
60774efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
60781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check that both strings are sequential ASCII.
60801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label runtime;
60814efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  __ JumpIfBothInstanceTypesAreNotSequentialAscii(
60824efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org      tmp1, tmp2, tmp3, tmp4, &runtime);
60831c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60841c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare flat ASCII strings. Returns when done.
60854efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (equality) {
60864efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    StringCompareStub::GenerateFlatAsciiStringEquals(
60874efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org        masm, left, right, tmp1, tmp2, tmp3);
60884efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  } else {
60894efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    StringCompareStub::GenerateCompareFlatAsciiStrings(
60904efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org        masm, left, right, tmp1, tmp2, tmp3, tmp4);
60914efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
60921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
60931c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Handle more complex cases in runtime.
60941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&runtime);
60951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Push(left, right);
60964efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (equality) {
60974efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
60984efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  } else {
60994efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
61004efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
61011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
61021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&miss);
61031c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  GenerateMiss(masm);
61041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
61051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
61061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
6107a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid ICCompareStub::GenerateObjects(MacroAssembler* masm) {
6108fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(state_ == CompareIC::OBJECT);
6109a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label miss;
6110a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ and_(r2, r1, Operand(r0));
61117b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(r2, &miss);
6112a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
6113a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE);
6114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(ne, &miss);
6115a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE);
6116a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(ne, &miss);
6117a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
6118a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  ASSERT(GetCondition() == eq);
6119a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ sub(r0, r0, Operand(r1));
6120a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Ret();
6121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
6122a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
6123a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GenerateMiss(masm);
6124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
6125a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
6126a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
612764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
612864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label miss;
612964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ and_(r2, r1, Operand(r0));
613064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ JumpIfSmi(r2, &miss);
613164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
613264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
613364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmp(r2, Operand(known_map_));
613464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ b(ne, &miss);
613564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmp(r3, Operand(known_map_));
613664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ b(ne, &miss);
613764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
613864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ sub(r0, r0, Operand(r1));
613964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ Ret();
614064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
614164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&miss);
614264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  GenerateMiss(masm);
614364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org}
614464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
614564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
6146a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
614764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid ICCompareStub::GenerateMiss(MacroAssembler* masm) {
6148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
614964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Call the runtime system in a fresh internal frame.
615064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    ExternalReference miss =
615164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
615264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
6153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
6154c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Push(r1, r0);
615564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ push(lr);
615664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ Push(r1, r0);
6157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(ip, Operand(Smi::FromInt(op_)));
6158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(ip);
6159c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallExternalReference(miss, 3);
616064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Compute the entry point of the rewritten stub.
616164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
616264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Restore registers.
616364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(lr);
616464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(r0);
616564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(r1);
6166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
616764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
6168a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Jump(r2);
6169a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
6170a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
6171a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
617283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.orgvoid DirectCEntryStub::Generate(MacroAssembler* masm) {
617383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  __ ldr(pc, MemOperand(sp, 0));
617483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org}
617583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
617683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
617783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.orgvoid DirectCEntryStub::GenerateCall(MacroAssembler* masm,
617849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org                                    Register target) {
61798432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  intptr_t code =
61808432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org      reinterpret_cast<intptr_t>(GetCode(masm->isolate()).location());
61818432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ mov(lr, Operand(code, RelocInfo::CODE_TARGET));
61827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
61837028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // Prevent literal pool emission during calculation of return address.
61847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  Assembler::BlockConstPoolScope block_const_pool(masm);
61857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
618649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Push return address (accessible to GC through exit frame pc).
61874acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Note that using pc with str is deprecated.
6188b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  Label start;
6189b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  __ bind(&start);
6190b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  __ add(ip, pc, Operand(Assembler::kInstrSize));
61914acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  __ str(ip, MemOperand(sp, 0));
619249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ Jump(target);  // Call the C++ function.
6193b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  ASSERT_EQ(Assembler::kInstrSize + Assembler::kPcLoadDelta,
6194b645116853c677aca8a316381b87441ba6004f67danno@chromium.org            masm->SizeOfCodeGeneratedSince(&start));
6195e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ VFPEnsureFPSCRState(r2);
619649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org}
619749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
619849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
6199750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
6200750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* miss,
6201750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* done,
6202750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register receiver,
6203750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register properties,
6204750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Handle<Name> name,
6205750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register scratch0) {
6206750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  ASSERT(name->IsUniqueName());
6207394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // If names of slots in range from 1 to kProbes - 1 for the hash value are
6208394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // not equal to the name and kProbes-th slot is not used (its name is the
6209394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // undefined value), it guarantees the hash table doesn't contain the
6210394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // property. It's true even if some slots represent deleted properties
6211967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org  // (their names are the hole value).
6212394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  for (int i = 0; i < kInlinedProbes; i++) {
6213394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // scratch0 points to properties hash.
6214394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Compute the masked index: (hash + i + i * i) & mask.
6215394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Register index = scratch0;
6216394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Capacity is smi 2^n.
6217394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
6218394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ sub(index, index, Operand(1));
6219394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ and_(index, index, Operand(
6220750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))));
6221394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6222394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Scale the index by multiplying by the entry size.
6223750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    ASSERT(NameDictionary::kEntrySize == 3);
6224394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
6225394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6226394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Register entity_name = scratch0;
6227394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Having undefined at this place means the name is not contained.
6228394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ASSERT_EQ(kSmiTagSize, 1);
6229394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Register tmp = properties;
6230394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ add(tmp, properties, Operand(index, LSL, 1));
6231394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
6232394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6233394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ASSERT(!tmp.is(entity_name));
6234394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
6235394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ cmp(entity_name, tmp);
6236394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ b(eq, done);
6237394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
623877802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    // Load the hole ready for use below:
623977802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
624077802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org
624177802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    // Stop if found the property.
624277802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ cmp(entity_name, Operand(Handle<Name>(name)));
624377802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ b(eq, miss);
624477802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org
624577802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    Label good;
624677802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ cmp(entity_name, tmp);
624777802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ b(eq, &good);
624877802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org
624977802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    // Check if the entry name is not a unique name.
625077802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
625177802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ ldrb(entity_name,
625277802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org            FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
62531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ JumpIfNotUniqueName(entity_name, miss);
625477802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ bind(&good);
625577802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org
625677802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    // Restore the properties.
625777802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org    __ ldr(properties,
625877802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org           FieldMemOperand(receiver, JSObject::kPropertiesOffset));
6259394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
6260394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6261394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  const int spill_mask =
6262394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() |
6263394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com       r2.bit() | r1.bit() | r0.bit());
6264394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6265394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ stm(db_w, sp, spill_mask);
6266394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
6267750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ mov(r1, Operand(Handle<Name>(name)));
6268750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  NameDictionaryLookupStub stub(NEGATIVE_LOOKUP);
6269394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ CallStub(&stub);
627059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
6271394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ ldm(ia_w, sp, spill_mask);
6272394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6273394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ b(eq, done);
6274394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ b(ne, miss);
6275394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
6276394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6277394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
6278750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Probe the name dictionary in the |elements| register. Jump to the
62791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// |done| label if a property with the given name is found. Jump to
62801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// the |miss| label otherwise.
62811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// If lookup was successful |scratch2| will be equal to elements + 4 * index.
6282750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
6283750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* miss,
6284750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* done,
6285750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register elements,
6286750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register name,
6287750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register scratch1,
6288750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register scratch2) {
62896e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!elements.is(scratch1));
62906e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!elements.is(scratch2));
62916e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!name.is(scratch1));
62926e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!name.is(scratch2));
62936e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com
6294750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ AssertName(name);
62951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
62961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compute the capacity mask.
62971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
6298bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(scratch1);
62991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ sub(scratch1, scratch1, Operand(1));
63001c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Generate an unrolled loop that performs a few probes before
63021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // giving up. Measurements done on Gmail indicate that 2 probes
63031c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // cover ~93% of loads from dictionaries.
63041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  for (int i = 0; i < kInlinedProbes; i++) {
63051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Compute the masked index: (hash + i + i * i) & mask.
6306750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset));
63071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (i > 0) {
63081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // Add the probe offset (i + i * i) left shifted to avoid right shifting
63091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // the hash in a separate instruction. The value hash + i + i * i is right
63101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // shifted in the following and instruction.
6311750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      ASSERT(NameDictionary::GetProbeOffset(i) <
6312750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org             1 << (32 - Name::kHashFieldOffset));
63131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      __ add(scratch2, scratch2, Operand(
6314750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org          NameDictionary::GetProbeOffset(i) << Name::kHashShift));
63151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
6316750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ and_(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift));
63171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Scale the index by multiplying by the element size.
6319750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    ASSERT(NameDictionary::kEntrySize == 3);
63201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // scratch2 = scratch2 * 3.
63211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
63221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Check if the key is identical to the name.
63241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ add(scratch2, elements, Operand(scratch2, LSL, 2));
63251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset));
63261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ cmp(name, Operand(ip));
63271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ b(eq, done);
63281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
63291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  const int spill_mask =
63311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      (lr.bit() | r6.bit() | r5.bit() | r4.bit() |
63321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org       r3.bit() | r2.bit() | r1.bit() | r0.bit()) &
63331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      ~(scratch1.bit() | scratch2.bit());
63341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ stm(db_w, sp, spill_mask);
63366e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  if (name.is(r0)) {
63376e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    ASSERT(!elements.is(r1));
63386e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    __ Move(r1, name);
63396e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    __ Move(r0, elements);
63406e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  } else {
63416e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    __ Move(r0, elements);
63426e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com    __ Move(r1, name);
63436e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  }
6344750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  NameDictionaryLookupStub stub(POSITIVE_LOOKUP);
63451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ CallStub(&stub);
634659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
63471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(scratch2, Operand(r2));
63481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldm(ia_w, sp, spill_mask);
63491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(ne, done);
63511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ b(eq, miss);
63521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
63531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
6355750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
6356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
6357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // we cannot call anything that could cause a GC from this stub.
63581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Registers:
6359750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  //  result: NameDictionary to probe
63601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  r1: key
6361750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  //  dictionary: NameDictionary to probe.
6362750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  //  index: will hold an index of entry if lookup is successful.
6363750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  //         might alias with result_.
63641c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Returns:
63651c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  result_ is zero if lookup failed, non zero otherwise.
63661c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register result = r0;
63681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register dictionary = r0;
63691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register key = r1;
63701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register index = r2;
63711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register mask = r3;
63721c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register hash = r4;
63731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register undefined = r5;
63741c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register entry_key = r6;
63751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
63771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ldr(mask, FieldMemOperand(dictionary, kCapacityOffset));
6379bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ SmiUntag(mask);
63801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ sub(mask, mask, Operand(1));
63811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
6382750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset));
63831c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63841c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
63851c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
63861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  for (int i = kInlinedProbes; i < kTotalProbes; i++) {
63871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Compute the masked index: (hash + i + i * i) & mask.
63881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Capacity is smi 2^n.
63891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (i > 0) {
63901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // Add the probe offset (i + i * i) left shifted to avoid right shifting
63911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // the hash in a separate instruction. The value hash + i + i * i is right
63921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // shifted in the following and instruction.
6393750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      ASSERT(NameDictionary::GetProbeOffset(i) <
6394750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org             1 << (32 - Name::kHashFieldOffset));
63951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      __ add(index, hash, Operand(
6396750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org          NameDictionary::GetProbeOffset(i) << Name::kHashShift));
63971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    } else {
63981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      __ mov(index, Operand(hash));
63991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
6400750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ and_(index, mask, Operand(index, LSR, Name::kHashShift));
64011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Scale the index by multiplying by the entry size.
6403750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    ASSERT(NameDictionary::kEntrySize == 3);
64041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
64051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    ASSERT_EQ(kSmiTagSize, 1);
64071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ add(index, dictionary, Operand(index, LSL, 2));
64081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset));
64091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Having undefined at this place means the name is not contained.
64111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ cmp(entry_key, Operand(undefined));
64121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ b(eq, &not_in_dictionary);
64131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Stop if found the property.
64151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ cmp(entry_key, Operand(key));
64161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ b(eq, &in_dictionary);
64171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
6419750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      // Check if the entry name is not a unique name.
64201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
64211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      __ ldrb(entry_key,
64221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org              FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
64231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary);
64241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
64251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
64261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&maybe_in_dictionary);
64281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // If we are doing negative lookup then probing failure should be
64291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // treated as a lookup success. For positive lookup probing failure
64301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // should be treated as lookup failure.
64311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  if (mode_ == POSITIVE_LOOKUP) {
6432ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org    __ mov(result, Operand::Zero());
64331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ Ret();
64341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
64351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&in_dictionary);
64371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(result, Operand(1));
64381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Ret();
64391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&not_in_dictionary);
6441ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org  __ mov(result, Operand::Zero());
64421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Ret();
64431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
64441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
64451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
6446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstruct AheadOfTimeWriteBarrierStubList {
6447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register object, value, address;
6448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  RememberedSetAction action;
6449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com};
6450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6451e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
64521456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#define REG(Name) { kRegister_ ## Name ## _Code }
6453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
64541456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgstatic const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
6455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Used in RegExpExecStub.
64561456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET },
6457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Used in CompileArrayPushCall.
6458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
6459c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Also used in KeyedStoreIC::GenerateGeneric.
64601456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET },
6461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Used in CompileStoreGlobal.
64621456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET },
6463c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
64641456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET },
64651456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET },
6466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
64671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r2), REG(r1), REG(r3), EMIT_REMEMBERED_SET },
64681456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r3), REG(r1), REG(r2), EMIT_REMEMBERED_SET },
6469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // KeyedStoreStubCompiler::GenerateStoreFastElement.
64701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r3), REG(r2), REG(r4), EMIT_REMEMBERED_SET },
64711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r2), REG(r3), REG(r4), EMIT_REMEMBERED_SET },
6472830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // ElementsTransitionGenerator::GenerateMapChangeElementTransition
6473830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // and ElementsTransitionGenerator::GenerateSmiToDouble
6474394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // and ElementsTransitionGenerator::GenerateDoubleToObject
64751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r2), REG(r3), REG(r9), EMIT_REMEMBERED_SET },
64761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r2), REG(r3), REG(r9), OMIT_REMEMBERED_SET },
6477394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ElementsTransitionGenerator::GenerateDoubleToObject
64781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r6), REG(r2), REG(r0), EMIT_REMEMBERED_SET },
64791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r2), REG(r6), REG(r9), EMIT_REMEMBERED_SET },
648004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // StoreArrayLiteralElementStub::Generate
64811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET },
64825a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // FastNewClosureStub::Generate
64835a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET },
648457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  // StringAddStub::Generate
648557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  { REG(r7), REG(r1), REG(r4), EMIT_REMEMBERED_SET },
648657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  { REG(r7), REG(r0), REG(r4), EMIT_REMEMBERED_SET },
6487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Null termination.
64881456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
6489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com};
6490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
64911456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#undef REG
6492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
649333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
6494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool RecordWriteStub::IsPregenerated() {
64951456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
6496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       !entry->object.is(no_reg);
6497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       entry++) {
6498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (object_.is(entry->object) &&
6499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        value_.is(entry->value) &&
6500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        address_.is(entry->address) &&
6501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        remembered_set_action_ == entry->action &&
6502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        save_fp_regs_mode_ == kDontSaveFPRegs) {
6503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return true;
6504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
6505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return false;
6507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
65108432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
65118432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Isolate* isolate) {
6512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  StoreBufferOverflowStub stub1(kDontSaveFPRegs);
65138432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  stub1.GetCode(isolate)->set_is_pregenerated(true);
651477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // Hydrogen code stubs need stub2 at snapshot time.
651577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  StoreBufferOverflowStub stub2(kSaveFPRegs);
651677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  stub2.GetCode(isolate)->set_is_pregenerated(true);
6517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
65208432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid RecordWriteStub::GenerateFixedRegStubsAheadOfTime(Isolate* isolate) {
65211456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
6522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       !entry->object.is(no_reg);
6523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       entry++) {
6524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    RecordWriteStub stub(entry->object,
6525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                         entry->value,
6526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                         entry->address,
6527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                         entry->action,
6528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                         kDontSaveFPRegs);
65298432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    stub.GetCode(isolate)->set_is_pregenerated(true);
6530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6532c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
653433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgbool CodeStub::CanUseFPRegisters() {
6535e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  return true;  // VFP2 is a base requirement for V8
653633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org}
653733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
653833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
6539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Takes the input in 3 registers: address_ value_ and object_.  A pointer to
6540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// the value has just been written into the object, now this stub makes sure
6541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// we keep the GC informed.  The word in the object where the value has been
6542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// written is in the address register.
6543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::Generate(MacroAssembler* masm) {
6544c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label skip_to_incremental_noncompacting;
6545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label skip_to_incremental_compacting;
6546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The first two instructions are generated with labels so as to get the
6548c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // offset fixed up correctly by the bind(Label*) call.  We patch it back and
6549c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // forth between a compare instructions (a nop in this position) and the
6550c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // real branch when we start and stop incremental heap marking.
6551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // See RecordWriteStub::Patch for details.
65527028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  {
65537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // Block literal pool emission, as the position of these two instructions
65547028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    // is assumed by the patching code.
65557028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Assembler::BlockConstPoolScope block_const_pool(masm);
65567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ b(&skip_to_incremental_noncompacting);
65577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    __ b(&skip_to_incremental_compacting);
65587028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
6559c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6560c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
6561c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
6562c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
6563c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
6564c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
6565c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
6566c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6567c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Ret();
6568c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6569c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&skip_to_incremental_noncompacting);
6570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  GenerateIncremental(masm, INCREMENTAL);
6571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6572c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&skip_to_incremental_compacting);
6573c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  GenerateIncremental(masm, INCREMENTAL_COMPACTION);
6574c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6575c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
6576c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Will be checked in IncrementalMarking::ActivateGeneratedStub.
6577c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(Assembler::GetBranchOffset(masm->instr_at(0)) < (1 << 12));
6578c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(Assembler::GetBranchOffset(masm->instr_at(4)) < (1 << 12));
6579c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  PatchBranchIntoNop(masm, 0);
6580c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  PatchBranchIntoNop(masm, Assembler::kInstrSize);
6581c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6582c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6583c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6584c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
6585c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Save(masm);
6586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
6588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label dont_need_remembered_set;
6589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6590c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0));
6591c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
6592c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           regs_.scratch0(),
6593c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           &dont_need_remembered_set);
6594c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6595c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CheckPageFlag(regs_.object(),
6596c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     regs_.scratch0(),
6597c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     1 << MemoryChunk::SCAN_ON_SCAVENGE,
6598c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     ne,
6599c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     &dont_need_remembered_set);
6600c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6601c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // First notify the incremental marker if necessary, then update the
6602c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // remembered set.
6603c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    CheckNeedsToInformIncrementalMarker(
6604c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
6605c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    InformIncrementalMarker(masm, mode);
6606c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    regs_.Restore(masm);
6607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
6608c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
6609c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
6610c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
6611c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
6612c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6613c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&dont_need_remembered_set);
6614c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6615c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6616c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CheckNeedsToInformIncrementalMarker(
6617c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
6618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  InformIncrementalMarker(masm, mode);
6619c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Restore(masm);
6620c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Ret();
6621c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6622c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6623c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6624c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) {
6625c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
6626c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  int argument_count = 3;
6627c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ PrepareCallCFunction(argument_count, regs_.scratch0());
6628c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Register address =
6629c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      r0.is(regs_.address()) ? regs_.scratch0() : regs_.address();
6630c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!address.is(regs_.object()));
6631c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(!address.is(r0));
6632c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Move(address, regs_.address());
6633c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Move(r0, regs_.object());
66348e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  __ Move(r1, address);
663532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ mov(r2, Operand(ExternalReference::isolate_address(masm->isolate())));
6636c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  AllowExternalCallThatCantCauseGC scope(masm);
6638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (mode == INCREMENTAL_COMPACTION) {
6639c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallCFunction(
6640c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ExternalReference::incremental_evacuation_record_write_function(
6641c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            masm->isolate()),
6642c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        argument_count);
6643c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
6644c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(mode == INCREMENTAL);
6645c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallCFunction(
6646c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ExternalReference::incremental_marking_record_write_function(
6647c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            masm->isolate()),
6648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        argument_count);
6649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
6651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6652c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6653c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker(
6655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    MacroAssembler* masm,
6656c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    OnNoNeedToInformIncrementalMarker on_no_need,
6657c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Mode mode) {
6658c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label on_black;
6659c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label need_incremental;
6660c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label need_incremental_pop_scratch;
6661c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
666233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ and_(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask));
666333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ ldr(regs_.scratch1(),
666433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org         MemOperand(regs_.scratch0(),
666533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                    MemoryChunk::kWriteBarrierCounterOffset));
666633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ sub(regs_.scratch1(), regs_.scratch1(), Operand(1), SetCC);
666733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ str(regs_.scratch1(),
666833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org         MemOperand(regs_.scratch0(),
666933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                    MemoryChunk::kWriteBarrierCounterOffset));
667033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ b(mi, &need_incremental);
667133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
6672c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Let's look at the color of the object:  If it is not black we don't have
6673c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // to inform the incremental marker.
6674c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
6675c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6676c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Restore(masm);
6677c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
6678c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
6679c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
6680c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
6681c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
6682c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
6683c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
6684c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Ret();
6685c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6686c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6687c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&on_black);
6688c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6689c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Get the value from the slot.
6690c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0));
6691c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6692c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (mode == INCREMENTAL_COMPACTION) {
6693c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label ensure_not_white;
6694c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6695c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CheckPageFlag(regs_.scratch0(),  // Contains value.
6696c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     regs_.scratch1(),  // Scratch.
6697c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     MemoryChunk::kEvacuationCandidateMask,
6698c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     eq,
6699c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     &ensure_not_white);
6700c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6701c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CheckPageFlag(regs_.object(),
6702c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     regs_.scratch1(),  // Scratch.
6703c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     MemoryChunk::kSkipEvacuationSlotsRecordingMask,
6704c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     eq,
6705c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     &need_incremental);
6706c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6707c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&ensure_not_white);
6708c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6709c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6710c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We need extra registers for this, so we push the object and the address
6711c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // register temporarily.
6712c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Push(regs_.object(), regs_.address());
6713c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ EnsureNotWhite(regs_.scratch0(),  // The value.
6714c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    regs_.scratch1(),  // Scratch.
6715c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    regs_.object(),  // Scratch.
6716c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    regs_.address(),  // Scratch.
6717c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    &need_incremental_pop_scratch);
6718c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Pop(regs_.object(), regs_.address());
6719c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6720c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Restore(masm);
6721c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
6722c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
6723c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
6724c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
6725c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
6726c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
6727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
6728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ Ret();
6729c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
6730c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6731c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&need_incremental_pop_scratch);
6732c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ Pop(regs_.object(), regs_.address());
6733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6734c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&need_incremental);
6735c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
6736c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Fall through when we need to inform the incremental marker.
6737c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
6738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
673904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
674004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.orgvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
674104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // ----------- S t a t e -------------
674204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  //  -- r0    : element value to store
674304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  //  -- r3    : element index as smi
6744b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  //  -- sp[0] : array literal index in function as smi
6745b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  //  -- sp[4] : array literal
6746b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // clobbers r1, r2, r4
674704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // -----------------------------------
674804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
674904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label element_done;
675004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label double_elements;
675104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label smi_element;
675204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label slow_elements;
675304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label fast_elements;
675404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
6755b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // Get array literal index, array literal and its map.
6756b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ ldr(r4, MemOperand(sp, 0 * kPointerSize));
6757b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
6758b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset));
6759b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
676004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ CheckFastElements(r2, r5, &double_elements);
6761830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
676204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ JumpIfSmi(r0, &smi_element);
6763830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  __ CheckFastSmiElements(r2, r5, &fast_elements);
676404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
676504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Store into the array literal requires a elements transition. Call into
676604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // the runtime.
676704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&slow_elements);
676804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // call.
676904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ Push(r1, r3, r0);
677004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
677104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset));
677204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ Push(r5, r4);
677304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
677404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
6775830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
677604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&fast_elements);
677704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
6778bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3));
677904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
678004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ str(r0, MemOperand(r6, 0));
678104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Update the write barrier for the array store.
678204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs,
678304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
678404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ Ret();
678504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
6786830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS,
6787830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // and value is Smi.
678804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&smi_element);
678904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
6790bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org  __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3));
679104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize));
679204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ Ret();
679304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
679404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
679504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&double_elements);
679604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
6797fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  __ StoreNumberToDoubleElements(r0, r3, r5, r6, d0, &slow_elements);
679804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ Ret();
679904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org}
680004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
6801753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6802068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.orgvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
6803e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
68048432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
68052f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  int parameter_count_offset =
68062f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
68072f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  __ ldr(r1, MemOperand(fp, parameter_count_offset));
6808f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  if (function_mode_ == JS_FUNCTION_STUB_MODE) {
6809f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    __ add(r1, r1, Operand(1));
6810f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  }
6811068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org  masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
68122f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  __ mov(r1, Operand(r1, LSL, kPointerSizeLog2));
68132f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  __ add(sp, sp, r1);
6814068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org  __ Ret();
6815068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org}
6816068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
6817068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
6818753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.orgvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
68191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  if (masm->isolate()->function_entry_hook() != NULL) {
68208e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org    PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize);
68211510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    AllowStubCallsScope allow_stub_calls(masm, true);
6822753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    ProfileEntryHookStub stub;
6823753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    __ push(lr);
6824753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    __ CallStub(&stub);
6825753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    __ pop(lr);
6826753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  }
6827753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org}
6828753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6829753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6830753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.orgvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) {
6831753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // The entry hook is a "push lr" instruction, followed by a call.
6832753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  const int32_t kReturnAddressDistanceFromFunctionStart =
683389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org      3 * Assembler::kInstrSize;
6834753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
68351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // This should contain all kCallerSaved registers.
68361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  const RegList kSavedRegs =
68371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      1 <<  0 |  // r0
68381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      1 <<  1 |  // r1
68391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      1 <<  2 |  // r2
68401510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      1 <<  3 |  // r3
68411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      1 <<  5 |  // r5
68421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      1 <<  9;   // r9
68431510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // We also save lr, so the count here is one higher than the mask indicates.
68441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  const int32_t kNumSavedRegs = 7;
68451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
68461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ASSERT((kCallerSaved & kSavedRegs) == kCallerSaved);
68471510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
68481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Save all caller-save registers as this may be called from anywhere.
68491510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ stm(db_w, sp, kSavedRegs | lr.bit());
6850753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6851753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Compute the function's address for the first argument.
6852753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ sub(r0, lr, Operand(kReturnAddressDistanceFromFunctionStart));
6853753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6854753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // The caller's return address is above the saved temporaries.
6855753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Grab that for the second argument to the hook.
6856753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ add(r1, sp, Operand(kNumSavedRegs * kPointerSize));
6857753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6858753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Align the stack if necessary.
6859753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  int frame_alignment = masm->ActivationFrameAlignment();
6860753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  if (frame_alignment > kPointerSize) {
6861753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    __ mov(r5, sp);
6862753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    ASSERT(IsPowerOf2(frame_alignment));
6863753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    __ and_(sp, sp, Operand(-frame_alignment));
6864753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  }
6865753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
686693a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_HOST_ARCH_ARM
68671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  int32_t entry_hook =
68681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook());
68691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ mov(ip, Operand(entry_hook));
6870753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org#else
6871753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Under the simulator we need to indirect the entry hook through a
6872753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // trampoline function at a known address.
68731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
6874753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ mov(ip, Operand(ExternalReference(&dispatcher,
6875753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org                                       ExternalReference::BUILTIN_CALL,
6876753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org                                       masm->isolate())));
6877753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org#endif
6878753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ Call(ip);
6879753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6880753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Restore the stack pointer if needed.
6881753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  if (frame_alignment > kPointerSize) {
6882753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    __ mov(sp, r5);
6883753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  }
6884753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
68851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Also pop pc to get Ret(0).
68861510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ ldm(ia_w, sp, kSavedRegs | pc.bit());
6887753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org}
6888753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
6889ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6890ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgtemplate<class T>
6891ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void CreateArrayDispatch(MacroAssembler* masm) {
6892ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  int last_index = GetSequenceIndexFromFastElementsKind(
6893ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      TERMINAL_FAST_ELEMENTS_KIND);
6894ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  for (int i = 0; i <= last_index; ++i) {
6895ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Label next;
6896ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6897ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ cmp(r3, Operand(kind));
6898ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ b(ne, &next);
6899ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    T stub(kind);
6900ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ TailCallStub(&stub);
6901ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ bind(&next);
6902ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
6903ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6904ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // If we reached this point there is a problem.
6905594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedElementsKindInArrayConstructor);
6906ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
6907ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6908ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6909ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
6910ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // r2 - type info cell
6911ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // r3 - kind
6912ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // r0 - number of arguments
6913ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // r1 - constructor?
6914ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // sp[0] - last argument
6915ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ASSERT(FAST_SMI_ELEMENTS == 0);
6916ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
6917ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ASSERT(FAST_ELEMENTS == 2);
6918ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ASSERT(FAST_HOLEY_ELEMENTS == 3);
6919ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ASSERT(FAST_DOUBLE_ELEMENTS == 4);
6920ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
6921ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6922ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // is the low bit set? If so, we are holey and that is good.
6923ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ tst(r3, Operand(1));
6924ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  Label normal_sequence;
6925ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ b(ne, &normal_sequence);
6926ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6927ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // look at the first argument
6928ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ ldr(r5, MemOperand(sp, 0));
6929ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ cmp(r5, Operand::Zero());
6930ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ b(eq, &normal_sequence);
6931ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6932ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // We are going to create a holey array, but our kind is non-holey.
6933bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Fix kind and retry (only if we have an allocation site in the cell).
6934ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ add(r3, r3, Operand(1));
6935bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
6936ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ b(eq, &normal_sequence);
6937bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset));
6938bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ ldr(r5, FieldMemOperand(r5, 0));
6939bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
6940bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ b(ne, &normal_sequence);
69411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
6942ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Save the resulting elements kind in type info
6943ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ SmiTag(r3);
6944bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset));
6945bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ str(r3, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset));
6946ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ SmiUntag(r3);
6947ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6948ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&normal_sequence);
6949ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  int last_index = GetSequenceIndexFromFastElementsKind(
6950ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      TERMINAL_FAST_ELEMENTS_KIND);
6951ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  for (int i = 0; i <= last_index; ++i) {
6952ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Label next;
6953ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6954ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ cmp(r3, Operand(kind));
6955ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ b(ne, &next);
6956ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    ArraySingleArgumentConstructorStub stub(kind);
6957ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ TailCallStub(&stub);
6958ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ bind(&next);
6959ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
6960ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6961ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // If we reached this point there is a problem.
6962594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedElementsKindInArrayConstructor);
6963ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
6964ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6965ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6966ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgtemplate<class T>
6967ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
6968ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  int to_index = GetSequenceIndexFromFastElementsKind(
6969ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      TERMINAL_FAST_ELEMENTS_KIND);
6970ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  for (int i = 0; i <= to_index; ++i) {
6971ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6972ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    T stub(kind);
6973ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    stub.GetCode(isolate)->set_is_pregenerated(true);
6974bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
69751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES);
6976d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org      stub1.GetCode(isolate)->set_is_pregenerated(true);
6977d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    }
6978ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
6979ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
6980ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6981ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6982ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
6983ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
6984ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      isolate);
6985ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
6986ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      isolate);
6987ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
6988ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      isolate);
6989ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
6990ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6991ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
6992d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
6993d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate) {
6994d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
6995d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  for (int i = 0; i < 2; i++) {
6996d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // For internal arrays we only need a few things
6997d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArrayNoArgumentConstructorStub stubh1(kinds[i]);
6998d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    stubh1.GetCode(isolate)->set_is_pregenerated(true);
6999d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArraySingleArgumentConstructorStub stubh2(kinds[i]);
7000d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    stubh2.GetCode(isolate)->set_is_pregenerated(true);
7001d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArrayNArgumentsConstructorStub stubh3(kinds[i]);
7002d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    stubh3.GetCode(isolate)->set_is_pregenerated(true);
7003d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
7004d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
7005d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7006d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7007ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayConstructorStub::Generate(MacroAssembler* masm) {
7008ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // ----------- S t a t e -------------
7009ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- r0 : argc (only if argument_count_ == ANY)
7010ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- r1 : constructor
7011ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- r2 : type info cell
7012ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- sp[0] : return address
7013ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- sp[4] : last argument
7014ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // -----------------------------------
7015ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  if (FLAG_debug_code) {
7016ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // The array construct code is only set for the global and natives
7017ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // builtin Array functions which always have maps.
7018ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
7019ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // Initial map for the builtin Array function should be a map.
7020ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
7021ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // Will both indicate a NULL and a Smi.
7022ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ tst(r3, Operand(kSmiTagMask));
7023594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
7024ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ CompareObjectType(r3, r3, r4, MAP_TYPE);
7025594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
7026ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
702741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    // We should either have undefined in ebx or a valid cell
7028ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Label okay_here;
702941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
7030bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
7031ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ b(eq, &okay_here);
7032ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ ldr(r3, FieldMemOperand(r2, 0));
703341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    __ cmp(r3, Operand(cell_map));
7034594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kExpectedPropertyCellInRegisterEbx);
7035ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ bind(&okay_here);
7036ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
7037ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
70381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Label no_info, switch_ready;
70391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Get the elements kind and case on that.
7040bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
70411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ b(eq, &no_info);
70421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
7043bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
7044bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // The type cell may have undefined in its value.
7045bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
7046bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ b(eq, &no_info);
7047bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
7048bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // The type cell has either an AllocationSite or a JSFunction
7049bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ ldr(r4, FieldMemOperand(r3, 0));
7050bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex);
7051bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ b(ne, &no_info);
7052bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
7053bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ ldr(r3, FieldMemOperand(r3, AllocationSite::kTransitionInfoOffset));
70541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ SmiUntag(r3);
70551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ jmp(&switch_ready);
70561510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ bind(&no_info);
70571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ mov(r3, Operand(GetInitialFastElementsKind()));
70581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ bind(&switch_ready);
70591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
70601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  if (argument_count_ == ANY) {
70611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Label not_zero_case, not_one_case;
70621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ tst(r0, r0);
70631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ b(ne, &not_zero_case);
70641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
70651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
70661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ bind(&not_zero_case);
70671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ cmp(r0, Operand(1));
70681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ b(gt, &not_one_case);
70691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    CreateArrayDispatchOneArgument(masm);
70701510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
70711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ bind(&not_one_case);
70721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
70731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  } else if (argument_count_ == NONE) {
70741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
70751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  } else if (argument_count_ == ONE) {
70761510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    CreateArrayDispatchOneArgument(masm);
70771510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  } else if (argument_count_ == MORE_THAN_ONE) {
70781510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7079ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  } else {
70801510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    UNREACHABLE();
7081ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
7082ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
7083ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
7084ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
7085d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStub::GenerateCase(
7086d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    MacroAssembler* masm, ElementsKind kind) {
7087d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Label not_zero_case, not_one_case;
7088d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Label normal_sequence;
7089d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7090d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ tst(r0, r0);
7091d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ b(ne, &not_zero_case);
7092d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InternalArrayNoArgumentConstructorStub stub0(kind);
7093d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ TailCallStub(&stub0);
7094d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7095d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&not_zero_case);
7096d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ cmp(r0, Operand(1));
7097d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ b(gt, &not_one_case);
7098d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7099d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  if (IsFastPackedElementsKind(kind)) {
7100d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // We might need to create a holey array
7101d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // look at the first argument
7102d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ ldr(r3, MemOperand(sp, 0));
7103d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ cmp(r3, Operand::Zero());
7104d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ b(eq, &normal_sequence);
7105d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7106d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArraySingleArgumentConstructorStub
7107d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org        stub1_holey(GetHoleyElementsKind(kind));
7108d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ TailCallStub(&stub1_holey);
7109d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
7110d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7111d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&normal_sequence);
7112d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InternalArraySingleArgumentConstructorStub stub1(kind);
7113d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ TailCallStub(&stub1);
7114d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7115d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&not_one_case);
7116d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InternalArrayNArgumentsConstructorStub stubN(kind);
7117d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ TailCallStub(&stubN);
7118d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
7119d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7120d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7121d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
7122d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // ----------- S t a t e -------------
7123d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- r0 : argc
7124d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- r1 : constructor
7125d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- sp[0] : return address
7126d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- sp[4] : last argument
7127d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // -----------------------------------
7128d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7129d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  if (FLAG_debug_code) {
7130d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // The array construct code is only set for the global and natives
7131d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // builtin Array functions which always have maps.
7132d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7133d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // Initial map for the builtin Array function should be a map.
7134d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
7135d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // Will both indicate a NULL and a Smi.
7136d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ tst(r3, Operand(kSmiTagMask));
7137594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(ne, kUnexpectedInitialMapForArrayFunction);
7138d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ CompareObjectType(r3, r3, r4, MAP_TYPE);
7139594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
7140d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
7141d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
71421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Figure out the right elements kind
71431510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
71441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Load the map's "bit field 2" into |result|. We only need the first byte,
71451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // but the following bit field extraction takes care of that anyway.
71461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset));
71471510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Retrieve elements_kind from bit field 2.
71481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ Ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount);
7149d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
71501510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  if (FLAG_debug_code) {
71511510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Label done;
7152d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ cmp(r3, Operand(FAST_ELEMENTS));
71531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ b(eq, &done);
71541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS));
71551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ Assert(eq,
7156594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org              kInvalidElementsKindForInternalArrayOrInternalPackedArray);
71571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ bind(&done);
71581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  }
7159d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
71601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Label fast_elements_case;
71611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ cmp(r3, Operand(FAST_ELEMENTS));
71621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ b(eq, &fast_elements_case);
71631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  GenerateCase(masm, FAST_HOLEY_ELEMENTS);
7164d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
71651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ bind(&fast_elements_case);
71661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  GenerateCase(masm, FAST_ELEMENTS);
7167d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
7168d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
7169d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
717065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#undef __
717165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
717265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} }  // namespace v8::internal
717365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
717465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif  // V8_TARGET_ARCH_ARM
7175