178d1ad443658709d6c27809001a0e71efd8b898fyangguo@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_IA32
3165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "bootstrapper.h"
337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#include "code-stubs.h"
34ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org#include "isolate.h"
357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#include "jsregexp.h"
3665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "regexp-macro-assembler.h"
3794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org#include "runtime.h"
38394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com#include "stub-cache.h"
390ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry#include "codegen.h"
404a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org#include "runtime.h"
4165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace v8 {
4365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace internal {
4465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
45a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
46662436e7b124b3535773535c671c53db322070b5verwaest@chromium.orgvoid FastNewClosureStub::InitializeInterfaceDescriptor(
47662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    Isolate* isolate,
48662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
49662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  static Register registers[] = { ebx };
50662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  descriptor->register_param_count_ = 1;
51662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  descriptor->register_params_ = registers;
52662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org  descriptor->deoptimization_handler_ =
53662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org      Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry;
54662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org}
55662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
56662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
57c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid ToNumberStub::InitializeInterfaceDescriptor(
58c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org    Isolate* isolate,
59c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
60c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  static Register registers[] = { eax };
61c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  descriptor->register_param_count_ = 1;
62c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  descriptor->register_params_ = registers;
63c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  descriptor->deoptimization_handler_ = NULL;
64c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org}
65c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
66c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
673d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.orgvoid NumberToStringStub::InitializeInterfaceDescriptor(
683d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    Isolate* isolate,
693d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
703d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  static Register registers[] = { eax };
713d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  descriptor->register_param_count_ = 1;
723d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  descriptor->register_params_ = registers;
73e7a07450b06d405206bf210de0aa6bbb440ab9a7bmeurer@chromium.org  descriptor->deoptimization_handler_ =
74e7a07450b06d405206bf210de0aa6bbb440ab9a7bmeurer@chromium.org      Runtime::FunctionForId(Runtime::kNumberToString)->entry;
753d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org}
763d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
773d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
78e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
79e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    Isolate* isolate,
80e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
81e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static Register registers[] = { eax, ebx, ecx };
82e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  descriptor->register_param_count_ = 3;
83e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  descriptor->register_params_ = registers;
84e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  descriptor->deoptimization_handler_ =
8537be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
86e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
87e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
88e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
8971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.orgvoid FastCloneShallowObjectStub::InitializeInterfaceDescriptor(
9071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    Isolate* isolate,
9171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
9271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  static Register registers[] = { eax, ebx, ecx, edx };
9371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  descriptor->register_param_count_ = 4;
9471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  descriptor->register_params_ = registers;
9571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  descriptor->deoptimization_handler_ =
96528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry;
9771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org}
9871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
9971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
100bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid CreateAllocationSiteStub::InitializeInterfaceDescriptor(
101bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    Isolate* isolate,
102bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
103bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  static Register registers[] = { ebx };
104bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  descriptor->register_param_count_ = 1;
105bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  descriptor->register_params_ = registers;
106bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  descriptor->deoptimization_handler_ = NULL;
107bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
108bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
109bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
110a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
111a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Isolate* isolate,
112a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
113a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static Register registers[] = { edx, ecx };
114a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  descriptor->register_param_count_ = 2;
115a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  descriptor->register_params_ = registers;
116a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  descriptor->deoptimization_handler_ =
117e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org      FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
118a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
119a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
120a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
121ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.orgvoid KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor(
122ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org    Isolate* isolate,
123ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
124ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  static Register registers[] = { edx, ecx };
125ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->register_param_count_ = 2;
126ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->register_params_ = registers;
127ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->deoptimization_handler_ =
128ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org      FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
129ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org}
130ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org
131ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org
13257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid LoadFieldStub::InitializeInterfaceDescriptor(
13357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Isolate* isolate,
13457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
13557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  static Register registers[] = { edx };
13657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_param_count_ = 1;
13757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_params_ = registers;
13857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->deoptimization_handler_ = NULL;
13957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org}
14057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
14157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
14257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid KeyedLoadFieldStub::InitializeInterfaceDescriptor(
14357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    Isolate* isolate,
14457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
14557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  static Register registers[] = { edx };
14657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_param_count_ = 1;
14757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->register_params_ = registers;
14857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  descriptor->deoptimization_handler_ = NULL;
14957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org}
15057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
15157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
152ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.orgvoid KeyedArrayCallStub::InitializeInterfaceDescriptor(
153ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org    Isolate* isolate,
154ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
155ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  static Register registers[] = { ecx };
156ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->register_param_count_ = 1;
157ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->register_params_ = registers;
158ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->continuation_type_ = TAIL_CALL_CONTINUATION;
159ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
160ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  descriptor->deoptimization_handler_ =
161ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org      FUNCTION_ADDR(KeyedCallIC_MissFromStubFailure);
162ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org}
163ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org
164ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org
1657bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.orgvoid KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
1667bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org    Isolate* isolate,
1677bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
1687bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  static Register registers[] = { edx, ecx, eax };
1697bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  descriptor->register_param_count_ = 3;
1707bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  descriptor->register_params_ = registers;
1717bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org  descriptor->deoptimization_handler_ =
1727bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure);
1737bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org}
1747bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org
1757bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org
17694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgvoid TransitionElementsKindStub::InitializeInterfaceDescriptor(
17794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    Isolate* isolate,
17894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
17994b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  static Register registers[] = { eax, ebx };
18094b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  descriptor->register_param_count_ = 2;
18194b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  descriptor->register_params_ = registers;
18294b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org  descriptor->deoptimization_handler_ =
18394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org      Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
18494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org}
18594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
18694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
187ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void InitializeArrayConstructorDescriptor(
188ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Isolate* isolate,
189ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    CodeStubInterfaceDescriptor* descriptor,
190ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    int constant_stack_parameter_count) {
1914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // register state
192ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // eax -- number of arguments
19357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  // edi -- function
1944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // ebx -- type info cell with elements kind
1950cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  static Register registers_variable_args[] = { edi, ebx, eax };
1960cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  static Register registers_no_args[] = { edi, ebx };
197ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
1980cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  if (constant_stack_parameter_count == 0) {
1990cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_param_count_ = 2;
2000cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_params_ = registers_no_args;
2010cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  } else {
202ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // stack param count needs (constructor pointer, and single argument)
2030cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
2040fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    descriptor->stack_parameter_count_ = eax;
2050cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_param_count_ = 3;
2060cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_params_ = registers_variable_args;
207ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
2080cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
209ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
210f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
2114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  descriptor->deoptimization_handler_ =
212dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
2134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
2144a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2154a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
216d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgstatic void InitializeInternalArrayConstructorDescriptor(
217d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
218d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor,
219d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    int constant_stack_parameter_count) {
220d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // register state
221d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // eax -- number of arguments
222d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // edi -- constructor function
2230cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  static Register registers_variable_args[] = { edi, eax };
2240cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  static Register registers_no_args[] = { edi };
225d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
2260cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  if (constant_stack_parameter_count == 0) {
2270cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_param_count_ = 1;
2280cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_params_ = registers_no_args;
2290cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  } else {
230d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // stack param count needs (constructor pointer, and single argument)
2310cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
2320fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    descriptor->stack_parameter_count_ = eax;
2330cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_param_count_ = 2;
2340cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    descriptor->register_params_ = registers_variable_args;
235d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
2360cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
237d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
238d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
239d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  descriptor->deoptimization_handler_ =
240dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
241d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
242d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
243d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
2444a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
2454a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Isolate* isolate,
2464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
247ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  InitializeArrayConstructorDescriptor(isolate, descriptor, 0);
2484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
2494a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
2524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Isolate* isolate,
2534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
254ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  InitializeArrayConstructorDescriptor(isolate, descriptor, 1);
2554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
2564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2584a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
2594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    Isolate* isolate,
2604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
261ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  InitializeArrayConstructorDescriptor(isolate, descriptor, -1);
262ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
263ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
264ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
265d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
266d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
267d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
268d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 0);
269d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
270d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
271d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
272d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
273d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
274d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
275d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 1);
276d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
277d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
278d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
279d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
280d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate,
281d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
282d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1);
283d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
284d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
285d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
286ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid CompareNilICStub::InitializeInterfaceDescriptor(
287ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Isolate* isolate,
288ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
289ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  static Register registers[] = { eax };
290ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->register_param_count_ = 1;
291ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->register_params_ = registers;
292ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  descriptor->deoptimization_handler_ =
293ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      FUNCTION_ADDR(CompareNilIC_Miss);
294a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  descriptor->SetMissHandler(
295a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
2964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
2974a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
298b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgvoid ToBooleanStub::InitializeInterfaceDescriptor(
299b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    Isolate* isolate,
300b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
301b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  static Register registers[] = { eax };
302b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->register_param_count_ = 1;
303b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->register_params_ = registers;
304b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->deoptimization_handler_ =
305b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      FUNCTION_ADDR(ToBooleanIC_Miss);
306b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  descriptor->SetMissHandler(
307b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
308b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org}
309b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org
3104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
311e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.orgvoid StoreGlobalStub::InitializeInterfaceDescriptor(
312e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    Isolate* isolate,
313e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
314e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  static Register registers[] = { edx, ecx, eax };
315e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  descriptor->register_param_count_ = 3;
316e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  descriptor->register_params_ = registers;
317e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org  descriptor->deoptimization_handler_ =
318e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org      FUNCTION_ADDR(StoreIC_MissFromStubFailure);
319e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org}
320e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
321e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
322ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgvoid ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
323ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    Isolate* isolate,
324ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
325ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  static Register registers[] = { eax, ebx, ecx, edx };
326ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  descriptor->register_param_count_ = 4;
327ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  descriptor->register_params_ = registers;
328ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  descriptor->deoptimization_handler_ =
329ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org      FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
330ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org}
331ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
332ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
333ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.orgvoid BinaryOpICStub::InitializeInterfaceDescriptor(
33425b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org    Isolate* isolate,
33525b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
33625b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org  static Register registers[] = { edx, eax };
33725b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org  descriptor->register_param_count_ = 2;
33825b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org  descriptor->register_params_ = registers;
33925b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org  descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss);
34025b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org  descriptor->SetMissHandler(
34125b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org      ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate));
34225b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org}
34325b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org
34425b0e21ac53cd2e892094493a65f75258fa977f0jkummerow@chromium.org
3450cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.orgvoid NewStringAddStub::InitializeInterfaceDescriptor(
3460cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    Isolate* isolate,
3470cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org    CodeStubInterfaceDescriptor* descriptor) {
3480cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  static Register registers[] = { edx, eax };
3490cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  descriptor->register_param_count_ = 2;
3500cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  descriptor->register_params_ = registers;
3510cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  descriptor->deoptimization_handler_ =
3520cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org      Runtime::FunctionForId(Runtime::kStringAdd)->entry;
3530cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org}
3540cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
3550cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
35665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#define __ ACCESS_MASM(masm)
3577a392b3bfb39dbbc1ff22f0b53109aa5763fde57whesse@chromium.org
35877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
35977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
36077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // Update the static counter each time a new code stub is generated.
36177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  Isolate* isolate = masm->isolate();
36277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  isolate->counters()->code_stubs()->Increment();
36377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
36477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
36577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  int param_count = descriptor->register_param_count_;
36677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  {
36777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    // Call the runtime system in a fresh internal frame.
36877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
36977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    ASSERT(descriptor->register_param_count_ == 0 ||
37077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org           eax.is(descriptor->register_params_[param_count - 1]));
37177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    // Push arguments
37277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    for (int i = 0; i < param_count; ++i) {
37377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      __ push(descriptor->register_params_[i]);
37477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    }
375a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org    ExternalReference miss = descriptor->miss_handler();
37677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    __ CallExternalReference(miss, descriptor->register_param_count_);
37777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  }
37877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
37977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  __ ret(0);
38077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org}
38177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
38277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
38365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FastNewContextStub::Generate(MacroAssembler* masm) {
38465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Try to allocate the context in new space.
38565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label gc;
3860ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
3872bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
3882bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org              eax, ebx, ecx, &gc, TAG_OBJECT);
38965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
39065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the function from the stack.
39165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(esp, 1 * kPointerSize));
39265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
393f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the object header.
3947979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
3956d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
3966d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org         factory->function_context_map());
39765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(eax, Context::kLengthOffset),
3980ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org         Immediate(Smi::FromInt(length)));
39965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
400f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the fixed slots.
4015d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ Set(ebx, Immediate(0));  // Set to NULL.
40265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
4036d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi);
40465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(eax, Context::SlotOffset(Context::EXTENSION_INDEX)), ebx);
40565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4066d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // Copy the global object from the previous context.
40746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
40846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)), ebx);
40965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Initialize the rest of the slots to undefined.
4117979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ mov(ebx, factory->undefined_value());
4120ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
41365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
41465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
41565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return and remove the on-stack parameter.
417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(esi, eax);
41865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(1 * kPointerSize);
41965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
42065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Need to collect. Call into runtime system.
42165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&gc);
4226d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
42365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
42465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
42565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
426a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.orgvoid FastNewBlockContextStub::Generate(MacroAssembler* masm) {
427a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Stack layout on entry:
428a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  //
429a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // [esp + (1 * kPointerSize)]: function
430a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // [esp + (2 * kPointerSize)]: serialized scope info
431a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
432a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Try to allocate the context in new space.
433a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  Label gc;
434a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
4352bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate(FixedArray::SizeFor(length), eax, ebx, ecx, &gc, TAG_OBJECT);
436a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
437a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Get the function or sentinel from the stack.
438a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ecx, Operand(esp, 1 * kPointerSize));
439a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
440a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Get the serialized scope info from the stack.
441a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ebx, Operand(esp, 2 * kPointerSize));
442a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
443f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the object header.
444a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  Factory* factory = masm->isolate()->factory();
445a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
446a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org         factory->block_context_map());
447a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(FieldOperand(eax, Context::kLengthOffset),
448a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org         Immediate(Smi::FromInt(length)));
449a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
45046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // If this block context is nested in the native context we get a smi
451a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // sentinel instead of a function. The block context should get the
45246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // canonical empty function of the native context as its closure which
453a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // we still have to look up.
454a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  Label after_sentinel;
455a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ JumpIfNotSmi(ecx, &after_sentinel, Label::kNear);
456a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  if (FLAG_debug_code) {
457a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    __ cmp(ecx, 0);
458594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(equal, kExpected0AsASmiSentinel);
459a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  }
460a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ecx, GlobalObjectOperand());
46146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(ecx, FieldOperand(ecx, GlobalObject::kNativeContextOffset));
462a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX));
463a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ bind(&after_sentinel);
464a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
465f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the fixed slots.
466a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx);
467a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi);
468a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx);
469a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
470a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Copy the global object from the previous context.
47146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(ebx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
47246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(ContextOperand(eax, Context::GLOBAL_OBJECT_INDEX), ebx);
473a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
474a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Initialize the rest of the slots to the hole value.
475a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  if (slots_ == 1) {
476a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    __ mov(ContextOperand(eax, Context::MIN_CONTEXT_SLOTS),
477a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org           factory->the_hole_value());
478a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  } else {
479a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    __ mov(ebx, factory->the_hole_value());
480a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    for (int i = 0; i < slots_; i++) {
481a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      __ mov(ContextOperand(eax, i + Context::MIN_CONTEXT_SLOTS), ebx);
482a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org    }
483a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  }
484a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
485a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Return and remove the on-stack parameters.
486a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ mov(esi, eax);
487a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ ret(2 * kPointerSize);
488a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
489a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  // Need to collect. Call into runtime system.
490a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ bind(&gc);
491a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org  __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
492a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org}
493a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
494a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org
495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We don't allow a GC during a store buffer overflow so there is no need to
497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // store the registers in any particular way, but we do have to store and
498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // restore them.
499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ pushad();
500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (save_doubles_ == kSaveFPRegs) {
501750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters));
503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      XMMRegister reg = XMMRegister::from_code(i);
5050fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org      __ movsd(Operand(esp, i * kDoubleSize), reg);
506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  const int argument_count = 1;
509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  AllowExternalCallThatCantCauseGC scope(masm);
511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ PrepareCallCFunction(argument_count, ecx);
512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(Operand(esp, 0 * kPointerSize),
51332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org         Immediate(ExternalReference::isolate_address(masm->isolate())));
514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ CallCFunction(
515c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference::store_buffer_overflow_function(masm->isolate()),
516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      argument_count);
517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (save_doubles_ == kSaveFPRegs) {
518750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      XMMRegister reg = XMMRegister::from_code(i);
5210fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org      __ movsd(reg, Operand(esp, i * kDoubleSize));
522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters));
524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ popad();
526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ ret(0);
527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
529c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
53065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgclass FloatingPointHelper : public AllStatic {
53165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public:
53265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  enum ArgLocation {
53365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    ARGS_ON_STACK,
53465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    ARGS_IN_REGISTERS
53565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  };
53665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
53765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Code pattern for loading a floating point value. Input value must
53865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // be either a smi or a heap number object (fp value). Requirements:
53965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // operand in register number. Returns operand as floating point number
54065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // on FPU stack.
54165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void LoadFloatOperand(MacroAssembler* masm, Register number);
54265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
54365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Test if operands are smi or number objects (fp). Requirements:
54465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // operand_1 in eax, operand_2 in edx; falls through on float
54565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // operands, jumps to the non_float label otherwise.
54665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void CheckFloatOperands(MacroAssembler* masm,
54765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                 Label* non_float,
54865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                 Register scratch);
54965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
55065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Test if operands are numbers (smi or HeapNumber objects), and load
55165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // them into xmm0 and xmm1 if they are.  Jump to label not_numbers if
55265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // either operand is not a number.  Operands are in edx and eax.
55365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Leaves operands unchanged.
55465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers);
55565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org};
55665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
55765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
558169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.orgvoid DoubleToIStub::Generate(MacroAssembler* masm) {
559169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  Register input_reg = this->source();
560169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  Register final_result_reg = this->destination();
561169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  ASSERT(is_truncating());
562169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
563169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  Label check_negative, process_64_bits, done, done_no_stash;
564169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
565169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  int double_offset = offset();
566169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
567169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Account for return address and saved regs if input is esp.
568169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (input_reg.is(esp)) double_offset += 3 * kPointerSize;
569169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
570169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  MemOperand mantissa_operand(MemOperand(input_reg, double_offset));
571169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  MemOperand exponent_operand(MemOperand(input_reg,
572ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                                         double_offset + kDoubleSize / 2));
573169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
574169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  Register scratch1;
575169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  {
576169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    Register scratch_candidates[3] = { ebx, edx, edi };
577169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    for (int i = 0; i < 3; i++) {
578169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      scratch1 = scratch_candidates[i];
579169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break;
580169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    }
581169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
582169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Since we must use ecx for shifts below, use some other register (eax)
583169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // to calculate the result if ecx is the requested return register.
584169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  Register result_reg = final_result_reg.is(ecx) ? eax : final_result_reg;
585169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Save ecx if it isn't the return register and therefore volatile, or if it
586169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // is the return register, then save the temp register we use in its stead for
587169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // the result.
588169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  Register save_reg = final_result_reg.is(ecx) ? eax : ecx;
589169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ push(scratch1);
590169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ push(save_reg);
591169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
592169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  bool stash_exponent_copy = !input_reg.is(esp);
593169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ mov(scratch1, mantissa_operand);
594169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (CpuFeatures::IsSupported(SSE3)) {
595750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE3);
5968e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    // Load x87 register with heap number.
597169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ fld_d(mantissa_operand);
598169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
599169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ mov(ecx, exponent_operand);
600169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (stash_exponent_copy) __ push(ecx);
601169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
602169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ and_(ecx, HeapNumber::kExponentMask);
603169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ shr(ecx, HeapNumber::kExponentShift);
604169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias));
605169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits));
606169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ j(below, &process_64_bits);
607169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
608169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Result is entirely in lower 32-bits of mantissa
609169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
610169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (CpuFeatures::IsSupported(SSE3)) {
611169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ fstp(0);
612169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
613169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ sub(ecx, Immediate(delta));
614169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ xor_(result_reg, result_reg);
615169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ cmp(ecx, Immediate(31));
616169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ j(above, &done);
617169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ shl_cl(scratch1);
618169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ jmp(&check_negative);
619169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
620169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ bind(&process_64_bits);
621169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (CpuFeatures::IsSupported(SSE3)) {
622169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    CpuFeatureScope scope(masm, SSE3);
623169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    if (stash_exponent_copy) {
624169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      // Already a copy of the exponent on the stack, overwrite it.
625169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
626169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ sub(esp, Immediate(kDoubleSize / 2));
627169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    } else {
628169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      // Reserve space for 64 bit answer.
629169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ sub(esp, Immediate(kDoubleSize));  // Nolint.
630169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    }
6318e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    // Do conversion, which cannot fail because we checked the exponent.
6328e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    __ fisttp_d(Operand(esp, 0));
633169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ mov(result_reg, Operand(esp, 0));  // Load low word of answer as result
634169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ add(esp, Immediate(kDoubleSize));
635169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ jmp(&done_no_stash);
6368e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  } else {
637169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    // Result must be extracted from shifted 32-bit mantissa
638169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ sub(ecx, Immediate(delta));
639169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ neg(ecx);
640169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    if (stash_exponent_copy) {
641169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ mov(result_reg, MemOperand(esp, 0));
642169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    } else {
643169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ mov(result_reg, exponent_operand);
644169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    }
645169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ and_(result_reg,
646169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org            Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32)));
647169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ add(result_reg,
648169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org           Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32)));
649169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ shrd(result_reg, scratch1);
650169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ shr_cl(result_reg);
651169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ test(ecx, Immediate(32));
652169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    if (CpuFeatures::IsSupported(CMOV)) {
653169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      CpuFeatureScope use_cmov(masm, CMOV);
654169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ cmov(not_equal, scratch1, result_reg);
655169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    } else {
656169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      Label skip_mov;
657169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ j(equal, &skip_mov, Label::kNear);
658169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ mov(scratch1, result_reg);
659169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      __ bind(&skip_mov);
6608e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org    }
661169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
6628e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
663169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // If the double was negative, negate the integer result.
664169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ bind(&check_negative);
665169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ mov(result_reg, scratch1);
666169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ neg(result_reg);
667169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (stash_exponent_copy) {
668169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ cmp(MemOperand(esp, 0), Immediate(0));
669169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  } else {
670169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ cmp(exponent_operand, Immediate(0));
671169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
672169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (CpuFeatures::IsSupported(CMOV)) {
673169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    CpuFeatureScope use_cmov(masm, CMOV);
674169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ cmov(greater, result_reg, scratch1);
675169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  } else {
676169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    Label skip_mov;
677169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ j(less_equal, &skip_mov, Label::kNear);
678169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ mov(result_reg, scratch1);
679169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ bind(&skip_mov);
6808e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  }
681169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
682169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Restore registers
683fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&done);
684169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (stash_exponent_copy) {
685169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ add(esp, Immediate(kDoubleSize / 2));
686169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
687169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ bind(&done_no_stash);
688169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  if (!final_result_reg.is(result_reg)) {
689169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    ASSERT(final_result_reg.is(ecx));
690169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    __ mov(final_result_reg, result_reg);
691169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  }
692169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ pop(save_reg);
693169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ pop(scratch1);
694169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ ret(0);
6958e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org}
6968e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
6978e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
69865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid TranscendentalCacheStub::Generate(MacroAssembler* masm) {
699023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // TAGGED case:
700023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //   Input:
701023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //     esp[4]: tagged number input argument (should be number).
702023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //     esp[0]: return address.
703023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //   Output:
704023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //     eax: tagged double result.
705023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // UNTAGGED case:
706023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //   Input::
707023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //     esp[0]: return address.
708023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //     xmm1: untagged double input argument
709023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //   Output:
710023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  //     xmm1: untagged double result.
711023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
71265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime_call;
71365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime_call_clear_stack;
714023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Label skip_cache;
715023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  const bool tagged = (argument_type_ == TAGGED);
716023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  if (tagged) {
717023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // Test that eax is a number.
71883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label input_not_smi;
71983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label loaded;
720023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ mov(eax, Operand(esp, kPointerSize));
7217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    __ JumpIfNotSmi(eax, &input_not_smi, Label::kNear);
722023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // Input is a smi. Untag and load it onto the FPU stack.
723023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // Then load the low and high words of the double into ebx, edx.
724023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    STATIC_ASSERT(kSmiTagSize == 1);
725023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ sar(eax, 1);
726c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(esp, Immediate(2 * kPointerSize));
727023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ mov(Operand(esp, 0), eax);
728023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fild_s(Operand(esp, 0));
729023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fst_d(Operand(esp, 0));
730023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ pop(edx);
731023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ pop(ebx);
73283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ jmp(&loaded, Label::kNear);
733023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&input_not_smi);
734023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // Check if input is a HeapNumber.
735023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
7367979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    Factory* factory = masm->isolate()->factory();
737c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(ebx, Immediate(factory->heap_number_map()));
738023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ j(not_equal, &runtime_call);
739023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // Input is a HeapNumber. Push it on the FPU stack and load its
740023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // low and high words into ebx, edx.
741023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
742023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
743023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
744023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
745023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&loaded);
746023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  } else {  // UNTAGGED.
747750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
748c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    if (CpuFeatures::IsSupported(SSE4_1)) {
749750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      CpuFeatureScope sse4_scope(masm, SSE4_1);
750c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ pextrd(edx, xmm1, 0x1);  // copy xmm1[63..32] to edx.
751023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    } else {
752023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org      __ pshufd(xmm0, xmm1, 0x1);
753c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ movd(edx, xmm0);
754023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    }
755c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ movd(ebx, xmm1);
756023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  }
75765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
758023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // ST[0] or xmm1  == double value
75965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx = low 32 bits of double value
76065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx = high 32 bits of double value
76165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Compute hash (the shifts are arithmetic):
76265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
76365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, ebx);
764c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ xor_(ecx, edx);
76565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, ecx);
76665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sar(eax, 16);
767c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ xor_(ecx, eax);
76865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, ecx);
76965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sar(eax, 8);
770c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ xor_(ecx, eax);
771ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
772c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ and_(ecx,
773ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org          Immediate(TranscendentalCache::SubCache::kCacheSize - 1));
77465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
775023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // ST[0] or xmm1 == double value.
77665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx = low 32 bits of double value.
77765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx = high 32 bits of double value.
77865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx = TranscendentalCache::hash(double value).
779ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ExternalReference cache_array =
780ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::transcendental_cache_array_address(masm->isolate());
781ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(eax, Immediate(cache_array));
782ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int cache_array_index =
783ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      type_ * sizeof(masm->isolate()->transcendental_cache()->caches_[0]);
784ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(eax, Operand(eax, cache_array_index));
78565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Eax points to the cache for the type type_.
78665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If NULL, the cache hasn't been initialized yet, so go through runtime.
787c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(eax, eax);
78865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(zero, &runtime_call_clear_stack);
78965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef DEBUG
79065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the layout of cache elements match expectations.
791ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  { TranscendentalCache::SubCache::Element test_elem[2];
79265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
79365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
79465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    char* elem_in0  = reinterpret_cast<char*>(&(test_elem[0].in[0]));
79565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    char* elem_in1  = reinterpret_cast<char*>(&(test_elem[0].in[1]));
79665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
79765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    CHECK_EQ(12, elem2_start - elem_start);  // Two uint_32's and a pointer.
79865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    CHECK_EQ(0, elem_in0 - elem_start);
79965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    CHECK_EQ(kIntSize, elem_in1 - elem_start);
80065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    CHECK_EQ(2 * kIntSize, elem_out - elem_start);
80165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
80265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif
80365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
80465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ecx, Operand(ecx, ecx, times_2, 0));
80565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ecx, Operand(eax, ecx, times_4, 0));
80665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if cache matches: Double value is stored in uint32_t[2] array.
80783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label cache_miss;
80865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(ebx, Operand(ecx, 0));
80983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &cache_miss, Label::kNear);
81065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(edx, Operand(ecx, kIntSize));
81183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &cache_miss, Label::kNear);
81265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Cache hit!
8131b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  Counters* counters = masm->isolate()->counters();
8141b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ IncrementCounter(counters->transcendental_cache_hit(), 1);
81565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(ecx, 2 * kIntSize));
816023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  if (tagged) {
817023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fstp(0);
818023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ ret(kPointerSize);
819023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  } else {  // UNTAGGED.
820750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
8210fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
822023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ Ret();
823023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  }
82465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
82565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&cache_miss);
8261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ IncrementCounter(counters->transcendental_cache_miss(), 1);
82765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Update cache with new value.
82865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // We are short on registers, so use no_reg as scratch.
82965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // This gives slightly larger code.
830023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  if (tagged) {
831023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
832023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  } else {  // UNTAGGED.
833750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
834023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
835c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(esp, Immediate(kDoubleSize));
8360fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(Operand(esp, 0), xmm1);
837023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fld_d(Operand(esp, 0));
838c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(esp, Immediate(kDoubleSize));
839023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  }
8409a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  GenerateOperation(masm, type_);
84165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(ecx, 0), ebx);
84265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(ecx, kIntSize), edx);
84365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(ecx, 2 * kIntSize), eax);
84465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
845023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  if (tagged) {
846023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ ret(kPointerSize);
847023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  } else {  // UNTAGGED.
848750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
8490fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
850023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ Ret();
851023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
852023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // Skip cache and return answer directly, only in untagged case.
853023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&skip_cache);
854c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(esp, Immediate(kDoubleSize));
8550fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(Operand(esp, 0), xmm1);
856023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fld_d(Operand(esp, 0));
8579a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    GenerateOperation(masm, type_);
858023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fstp_d(Operand(esp, 0));
8590fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm1, Operand(esp, 0));
860c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(esp, Immediate(kDoubleSize));
861023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // We return the value in xmm1 without adding it to the cache, but
862023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    // we cause a scavenging GC so that future allocations will succeed.
863c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
864c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
865c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Allocate an unused object bigger than a HeapNumber.
866c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(Immediate(Smi::FromInt(2 * kDoubleSize)));
867c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
868c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
869023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ Ret();
870023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  }
87165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
872023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Call runtime, doing whatever allocation and cleanup is necessary.
873023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  if (tagged) {
874023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&runtime_call_clear_stack);
875023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ fstp(0);
876023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&runtime_call);
877ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ExternalReference runtime =
878ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org        ExternalReference(RuntimeFunction(), masm->isolate());
879ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    __ TailCallExternalReference(runtime, 1, 1);
880023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  } else {  // UNTAGGED.
881750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope(masm, SSE2);
882023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&runtime_call_clear_stack);
883023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ bind(&runtime_call);
884023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
8850fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
886c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
887c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
888c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(eax);
889c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallRuntime(RuntimeFunction(), 1);
890c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
8910fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
892023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org    __ Ret();
893023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  }
89465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
89565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
89665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
89765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgRuntime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
89865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  switch (type_) {
89965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    case TranscendentalCache::SIN: return Runtime::kMath_sin;
90065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    case TranscendentalCache::COS: return Runtime::kMath_cos;
9011b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    case TranscendentalCache::TAN: return Runtime::kMath_tan;
902a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    case TranscendentalCache::LOG: return Runtime::kMath_log;
90365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    default:
90465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      UNIMPLEMENTED();
90565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      return Runtime::kAbort;
90665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
90765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
90865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
90965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
9109a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.orgvoid TranscendentalCacheStub::GenerateOperation(
9119a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    MacroAssembler* masm, TranscendentalCache::Type type) {
91265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Only free register is edi.
913023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Input value is on FP stack, and also in ebx/edx.
914023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Input value is possibly in xmm1.
915023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Address of result (a newly allocated HeapNumber) may be in eax.
9169a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  if (type == TranscendentalCache::SIN ||
9179a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org      type == TranscendentalCache::COS ||
9189a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org      type == TranscendentalCache::TAN) {
919a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Both fsin and fcos require arguments in the range +/-2^63 and
920a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // return NaN for infinities and NaN. They can share all code except
921a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // the actual fsin/fcos operation.
92283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label in_range, done;
923a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // If argument is outside the range -2^63..2^63, fsin/cos doesn't
924a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // work. We must reduce it to the appropriate range.
925a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(edi, edx);
926c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ and_(edi, Immediate(0x7ff00000));  // Exponent only.
927a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    int supported_exponent_limit =
928a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift;
929c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(edi, Immediate(supported_exponent_limit));
9307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ j(below, &in_range, Label::kNear);
931a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Check for infinity and NaN. Both return NaN for sin.
932c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(edi, Immediate(0x7ff00000));
93383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label non_nan_result;
9347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ j(not_equal, &non_nan_result, Label::kNear);
935a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Input is +/-Infinity or NaN. Result is NaN.
936a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fstp(0);
937a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // NaN is represented by 0x7ff8000000000000.
938a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push(Immediate(0x7ff80000));
939a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push(Immediate(0));
940a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fld_d(Operand(esp, 0));
941c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(esp, Immediate(2 * kPointerSize));
94283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ jmp(&done, Label::kNear);
94365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
944a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ bind(&non_nan_result);
94565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
946a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Use fpmod to restrict argument to the range +/-2*PI.
947a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(edi, eax);  // Save eax before using fnstsw_ax.
948a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fldpi();
949a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fadd(0);
950a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fld(1);
951a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // FPU Stack: input, 2*pi, input.
952a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    {
95383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label no_exceptions;
954a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ fwait();
955a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ fnstsw_ax();
956a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      // Clear if Illegal Operand or Zero Division exceptions are set.
957c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ test(eax, Immediate(5));
95883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      __ j(zero, &no_exceptions, Label::kNear);
959a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ fnclex();
960a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ bind(&no_exceptions);
961a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    }
96265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
963a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Compute st(0) % st(1)
964a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    {
96583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label partial_remainder_loop;
966a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ bind(&partial_remainder_loop);
967a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ fprem1();
968a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ fwait();
969a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ fnstsw_ax();
970c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ test(eax, Immediate(0x400 /* C2 */));
971a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      // If C2 is set, computation only has partial result. Loop to
972a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      // continue computation.
973a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      __ j(not_zero, &partial_remainder_loop);
974a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    }
975a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // FPU Stack: input, 2*pi, input % 2*pi
976a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fstp(2);
977a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fstp(0);
978a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(eax, edi);  // Restore eax (allocated HeapNumber pointer).
979a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
980a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // FPU Stack: input % 2*pi
981a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ bind(&in_range);
9829a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    switch (type) {
983a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      case TranscendentalCache::SIN:
984a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        __ fsin();
985a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        break;
986a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      case TranscendentalCache::COS:
987a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        __ fcos();
988a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        break;
9891b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      case TranscendentalCache::TAN:
9901b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        // FPTAN calculates tangent onto st(0) and pushes 1.0 onto the
9911b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        // FP register stack.
9921b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        __ fptan();
9931b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        __ fstp(0);  // Pop FP register stack.
9941b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        break;
995a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      default:
996a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        UNREACHABLE();
997a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    }
998a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ bind(&done);
999a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  } else {
10009a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    ASSERT(type == TranscendentalCache::LOG);
1001a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fldln2();
1002a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fxch();
1003a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ fyl2x();
100465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
100565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
100665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
100765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
100865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
100965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           Register number) {
101083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label load_smi, done;
101165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
10127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(number, &load_smi, Label::kNear);
101365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
101483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&done, Label::kNear);
101565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
101665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&load_smi);
101765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(number);
101865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(number);
101965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ fild_s(Operand(esp, 0));
102065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(number);
102165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
102265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
102365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
102465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
102565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
102665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
102765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                           Label* not_numbers) {
102883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
102965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load operand in edx into xmm0, or branch to not_numbers.
10307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(edx, &load_smi_edx, Label::kNear);
10317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
10327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map());
103365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, not_numbers);  // Argument in edx is not a number.
10340fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
103565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&load_eax);
103665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load operand in eax into xmm1, or branch to not_numbers.
10377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(eax, &load_smi_eax, Label::kNear);
10387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map());
103983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(equal, &load_float_eax, Label::kNear);
104065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(not_numbers);  // Argument in eax is not a number.
104165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&load_smi_edx);
104265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(edx);  // Untag smi before converting to float.
1043528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ Cvtsi2sd(xmm0, edx);
104465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiTag(edx);  // Retag smi for heap number overwriting test.
104565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&load_eax);
104665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&load_smi_eax);
104765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(eax);  // Untag smi before converting to float.
1048528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ Cvtsi2sd(xmm1, eax);
104965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiTag(eax);  // Retag smi for heap number overwriting test.
105083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&done, Label::kNear);
105165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&load_float_eax);
10520fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org  __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
105365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
105465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
105565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
105665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
105765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
105865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             Label* non_float,
105965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             Register scratch) {
106083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label test_other, done;
106165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Test if both operands are floats or smi -> scratch=k_is_float;
106265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Otherwise scratch = k_not_float.
10637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(edx, &test_other, Label::kNear);
106465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
10657979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
10667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(scratch, factory->heap_number_map());
106765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, non_float);  // argument in edx is not a number -> NaN
106865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
106965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&test_other);
10707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(eax, &done, Label::kNear);
107165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
10727979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(scratch, factory->heap_number_map());
107365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, non_float);  // argument in eax is not a number -> NaN
107465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
107565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fall-through: Both operands are numbers.
107665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
107765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
107865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
107965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1080a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid MathPowStub::Generate(MacroAssembler* masm) {
1081750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  CpuFeatureScope use_sse2(masm, SSE2);
10827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
108364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register exponent = eax;
108464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register base = edx;
108564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const Register scratch = ecx;
108664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const XMMRegister double_result = xmm3;
108764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const XMMRegister double_base = xmm2;
108864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const XMMRegister double_exponent = xmm1;
108964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const XMMRegister double_scratch = xmm4;
109064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
109164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label call_runtime, done, exponent_not_smi, int_exponent;
109264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
109364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Save 1 in double_result - we need this several times later on.
109464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(scratch, Immediate(1));
1095528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ Cvtsi2sd(double_result, scratch);
109664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
109764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (exponent_type_ == ON_STACK) {
109864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    Label base_is_smi, unpack_exponent;
109964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // The exponent and base are supplied as arguments on the stack.
110064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // This can only happen if the stub is called from non-optimized code.
110164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Load input parameters from stack.
110264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ mov(base, Operand(esp, 2 * kPointerSize));
110364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ mov(exponent, Operand(esp, 1 * kPointerSize));
110464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
110564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ JumpIfSmi(base, &base_is_smi, Label::kNear);
110664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ cmp(FieldOperand(base, HeapObject::kMapOffset),
110764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org           factory->heap_number_map());
110864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ j(not_equal, &call_runtime);
110964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
11100fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
111164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&unpack_exponent, Label::kNear);
111264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
111364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&base_is_smi);
111464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ SmiUntag(base);
1115528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    __ Cvtsi2sd(double_base, base);
111664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
111764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&unpack_exponent);
111864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
111964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ SmiUntag(exponent);
112064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&int_exponent);
112164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
112264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&exponent_not_smi);
112364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ cmp(FieldOperand(exponent, HeapObject::kMapOffset),
112464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org           factory->heap_number_map());
112564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ j(not_equal, &call_runtime);
11260fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(double_exponent,
112764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              FieldOperand(exponent, HeapNumber::kValueOffset));
112864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else if (exponent_type_ == TAGGED) {
112964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
113064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ SmiUntag(exponent);
113164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&int_exponent);
113264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
113364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&exponent_not_smi);
11340fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(double_exponent,
113564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              FieldOperand(exponent, HeapNumber::kValueOffset));
113664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
1137a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
113864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (exponent_type_ != INTEGER) {
11398fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org    Label fast_power, try_arithmetic_simplification;
11408fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org    __ DoubleToI(exponent, double_exponent, double_scratch,
11418fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org                 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification);
11428fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org    __ jmp(&int_exponent);
11438fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org
11448fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org    __ bind(&try_arithmetic_simplification);
114564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Skip to runtime if possibly NaN (indicated by the indefinite integer).
11468fa5bd929d2f128e3d554398bd085b3c2f98e23bjkummerow@chromium.org    __ cvttsd2si(exponent, Operand(double_exponent));
114764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ cmp(exponent, Immediate(0x80000000u));
114864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ j(equal, &call_runtime);
114964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
115064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    if (exponent_type_ == ON_STACK) {
115164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Detect square root case.  Crankshaft detects constant +/-0.5 at
115264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // compile time and uses DoMathPowHalf instead.  We then skip this check
115364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // for non-constant cases of +/-0.5 as these hardly occur.
115464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      Label continue_sqrt, continue_rsqrt, not_plus_half;
115564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Test for 0.5.
115664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Load double_scratch with 0.5.
115764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ mov(scratch, Immediate(0x3F000000u));
115864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ movd(double_scratch, scratch);
115964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ cvtss2sd(double_scratch, double_scratch);
116064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Already ruled out NaNs for exponent.
116164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ ucomisd(double_scratch, double_exponent);
116264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ j(not_equal, &not_plus_half, Label::kNear);
116364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
116464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Calculates square root of base.  Check for the special case of
116564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
116664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // According to IEEE-754, single-precision -Infinity has the highest
116764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // 9 bits set and the lowest 23 bits cleared.
116864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ mov(scratch, 0xFF800000u);
116964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ movd(double_scratch, scratch);
117064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ cvtss2sd(double_scratch, double_scratch);
117164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ ucomisd(double_base, double_scratch);
117264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Comparing -Infinity with NaN results in "unordered", which sets the
117364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // zero flag as if both were equal.  However, it also sets the carry flag.
117464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ j(not_equal, &continue_sqrt, Label::kNear);
117564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ j(carry, &continue_sqrt, Label::kNear);
117664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
117764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Set result to Infinity in the special case.
117864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ xorps(double_result, double_result);
117964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ subsd(double_result, double_scratch);
118064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ jmp(&done);
118164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
118264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ bind(&continue_sqrt);
118364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
118464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ xorps(double_scratch, double_scratch);
118564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ addsd(double_scratch, double_base);  // Convert -0 to +0.
118664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ sqrtsd(double_result, double_scratch);
118764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ jmp(&done);
118864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
118964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Test for -0.5.
119064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ bind(&not_plus_half);
119164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Load double_exponent with -0.5 by substracting 1.
119264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ subsd(double_scratch, double_result);
119364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Already ruled out NaNs for exponent.
119464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ ucomisd(double_scratch, double_exponent);
119564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ j(not_equal, &fast_power, Label::kNear);
119664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
119764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Calculates reciprocal of square root of base.  Check for the special
119864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
119964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // According to IEEE-754, single-precision -Infinity has the highest
120064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // 9 bits set and the lowest 23 bits cleared.
120164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ mov(scratch, 0xFF800000u);
120264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ movd(double_scratch, scratch);
120364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ cvtss2sd(double_scratch, double_scratch);
120464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ ucomisd(double_base, double_scratch);
120564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Comparing -Infinity with NaN results in "unordered", which sets the
120664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // zero flag as if both were equal.  However, it also sets the carry flag.
120764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ j(not_equal, &continue_rsqrt, Label::kNear);
120864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ j(carry, &continue_rsqrt, Label::kNear);
120964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
121064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // Set result to 0 in the special case.
121164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ xorps(double_result, double_result);
121264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ jmp(&done);
121364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
121464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ bind(&continue_rsqrt);
121564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
121664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ xorps(double_exponent, double_exponent);
121764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ addsd(double_exponent, double_base);  // Convert -0 to +0.
121864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ sqrtsd(double_exponent, double_exponent);
121964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ divsd(double_result, double_exponent);
122064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ jmp(&done);
122164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    }
1222a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
122364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Using FPU instructions to calculate power.
122464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    Label fast_power_failed;
122564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&fast_power);
122664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fnclex();  // Clear flags to catch exceptions later.
122764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Transfer (B)ase and (E)xponent onto the FPU register stack.
122864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ sub(esp, Immediate(kDoubleSize));
12290fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(Operand(esp, 0), double_exponent);
123064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fld_d(Operand(esp, 0));  // E
12310fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(Operand(esp, 0), double_base);
123264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fld_d(Operand(esp, 0));  // B, E
123364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
123464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Exponent is in st(1) and base is in st(0)
123564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B)
123664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // FYL2X calculates st(1) * log2(st(0))
123764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fyl2x();    // X
123864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fld(0);     // X, X
123964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ frndint();  // rnd(X), X
124064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fsub(1);    // rnd(X), X-rnd(X)
124164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fxch(1);    // X - rnd(X), rnd(X)
124264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1
124364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ f2xm1();    // 2^(X-rnd(X)) - 1, rnd(X)
124464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fld1();     // 1, 2^(X-rnd(X)) - 1, rnd(X)
12451f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ faddp(1);   // 2^(X-rnd(X)), rnd(X)
124664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // FSCALE calculates st(0) * 2^st(1)
124764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fscale();   // 2^X, rnd(X)
12481f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    __ fstp(1);    // 2^X
124964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Bail out to runtime in case of exceptions in the status word.
125064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fnstsw_ax();
125164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ test_b(eax, 0x5F);  // We check for all but precision exception.
125264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ j(not_zero, &fast_power_failed, Label::kNear);
125364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fstp_d(Operand(esp, 0));
12540fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(double_result, Operand(esp, 0));
125564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ add(esp, Immediate(kDoubleSize));
125664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&done);
1257a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
125864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&fast_power_failed);
125964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fninit();
126064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ add(esp, Immediate(kDoubleSize));
126164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ jmp(&call_runtime);
126264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
126364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
126464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Calculate power with integer exponent.
126564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&int_exponent);
126664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  const XMMRegister double_scratch2 = double_exponent;
126764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(scratch, exponent);  // Back up exponent.
126864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movsd(double_scratch, double_base);  // Back up base.
126964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movsd(double_scratch2, double_result);  // Load double_exponent with 1.
1270a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1271a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Get absolute value of exponent.
127233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  Label no_neg, while_true, while_false;
127364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test(scratch, scratch);
127464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(positive, &no_neg, Label::kNear);
127564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ neg(scratch);
1276a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&no_neg);
1277a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
127856c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ j(zero, &while_false, Label::kNear);
127964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ shr(scratch, 1);
128056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Above condition means CF==0 && ZF==0.  This means that the
128156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // bit that has been shifted out is 0 and the result is not 0.
128256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ j(above, &while_true, Label::kNear);
128356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ movsd(double_result, double_scratch);
128456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ j(zero, &while_false, Label::kNear);
1285a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
128656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ bind(&while_true);
128756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ shr(scratch, 1);
128864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mulsd(double_scratch, double_scratch);
128956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ j(above, &while_true, Label::kNear);
129056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ mulsd(double_result, double_scratch);
129164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_zero, &while_true);
1292a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
129356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ bind(&while_false);
129464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // scratch has the original value of the exponent - if the exponent is
129564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // negative, return 1/result.
129664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test(exponent, exponent);
129764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(positive, &done);
129864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ divsd(double_scratch2, double_result);
129964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movsd(double_result, double_scratch2);
130064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Test whether result is zero.  Bail out to check for subnormal result.
130164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
130264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ xorps(double_scratch2, double_scratch2);
130364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ucomisd(double_scratch2, double_result);  // Result cannot be NaN.
130464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // double_exponent aliased as double_scratch2 has already been overwritten
130564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // and may not have contained the exponent value in the first place when the
130664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // exponent is a smi.  We reset it with exponent value before bailing out.
130764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &done);
1308528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ Cvtsi2sd(double_exponent, exponent);
130964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
131064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Returning or bailing out.
131164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Counters* counters = masm->isolate()->counters();
131264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  if (exponent_type_ == ON_STACK) {
131364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // The arguments are still on the stack.
131464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&call_runtime);
131564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
1316a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
131764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // The stub is called from non-optimized code, which expects the result
131864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // as heap number in exponent.
131964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&done);
132064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ AllocateHeapNumber(eax, scratch, base, &call_runtime);
13210fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result);
132264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ IncrementCounter(counters->math_pow(), 1);
132364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ ret(2 * kPointerSize);
132464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else {
132564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&call_runtime);
132664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    {
132764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      AllowExternalCallThatCantCauseGC scope(masm);
132864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ PrepareCallCFunction(4, scratch);
13290fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org      __ movsd(Operand(esp, 0 * kDoubleSize), double_base);
13300fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org      __ movsd(Operand(esp, 1 * kDoubleSize), double_exponent);
133164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      __ CallCFunction(
133264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          ExternalReference::power_double_double_function(masm->isolate()), 4);
133364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    }
133464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Return value is in st(0) on ia32.
133564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Store it into the (fixed) result register.
133664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ sub(esp, Immediate(kDoubleSize));
133764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ fstp_d(Operand(esp, 0));
13380fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(double_result, Operand(esp, 0));
133964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ add(esp, Immediate(kDoubleSize));
1340a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
134164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ bind(&done);
134264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ IncrementCounter(counters->math_pow(), 1);
134364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ ret(0);
134464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
1345a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
1346a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1347a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
13486bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) {
13496bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  // ----------- S t a t e -------------
13506bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  //  -- ecx    : name
13516bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  //  -- edx    : receiver
13526bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  //  -- esp[0] : return address
13536bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  // -----------------------------------
13546bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  Label miss;
13556bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13566bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (kind() == Code::KEYED_LOAD_IC) {
13574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ cmp(ecx, Immediate(masm->isolate()->factory()->prototype_string()));
13586bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    __ j(not_equal, &miss);
13596bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  }
13606bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13616bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
13626bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  __ bind(&miss);
1363bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  StubCompiler::TailCallBuiltin(
1364bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
13656bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org}
13666bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13676bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13686bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgvoid StringLengthStub::Generate(MacroAssembler* masm) {
13696bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  // ----------- S t a t e -------------
13706bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  //  -- ecx    : name
13716bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  //  -- edx    : receiver
13726bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  //  -- esp[0] : return address
13736bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  // -----------------------------------
13746bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  Label miss;
13756bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13766bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (kind() == Code::KEYED_LOAD_IC) {
13774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
13786bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    __ j(not_equal, &miss);
13796bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  }
13806bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
1381528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss);
13826bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  __ bind(&miss);
1383bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  StubCompiler::TailCallBuiltin(
1384bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
13856bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org}
13866bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13876bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
1388d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.orgvoid StoreArrayLengthStub::Generate(MacroAssembler* masm) {
1389d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // ----------- S t a t e -------------
1390d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  //  -- eax    : value
1391d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  //  -- ecx    : name
1392d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  //  -- edx    : receiver
1393d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  //  -- esp[0] : return address
1394d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // -----------------------------------
1395d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  //
1396d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // This accepts as a receiver anything JSArray::SetElementsLength accepts
1397d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // (currently anything except for external arrays which means anything with
1398d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // elements of FixedArray type).  Value must be a number, but only smis are
1399d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // accepted as the most common case.
1400d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1401d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Label miss;
1402d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1403d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Register receiver = edx;
1404d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Register value = eax;
1405d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  Register scratch = ebx;
1406d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1407750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  if (kind() == Code::KEYED_STORE_IC) {
14084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
1409d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org    __ j(not_equal, &miss);
1410d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  }
1411d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1412d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that the receiver isn't a smi.
1413d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ JumpIfSmi(receiver, &miss);
1414d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1415d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that the object is a JS array.
1416d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1417d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ j(not_equal, &miss);
1418d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1419d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that elements are FixedArray.
1420d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // We rely on StoreIC_ArrayLength below to deal with all types of
1421d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // fast elements (including COW).
1422d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1423d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1424d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ j(not_equal, &miss);
1425d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1426d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that the array has fast properties, otherwise the length
1427d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // property might have been redefined.
1428d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ mov(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
1429d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
1430d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org                 Heap::kHashTableMapRootIndex);
1431d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ j(equal, &miss);
1432d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1433d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Check that value is a smi.
1434d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ JumpIfNotSmi(value, &miss);
1435d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1436d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  // Prepare tail call to StoreIC_ArrayLength.
1437d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ pop(scratch);
1438d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ push(receiver);
1439d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ push(value);
1440d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ push(scratch);  // return address
1441d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1442d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  ExternalReference ref =
1443d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org      ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
1444d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ TailCallExternalReference(ref, 2, 1);
1445d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1446d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org  __ bind(&miss);
1447d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1448bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  StubCompiler::TailCallBuiltin(
1449bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      masm, BaseLoadStoreStubCompiler::MissBuiltin(kind()));
1450d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org}
1451d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
1452d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org
145365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
145465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The key is in edx and the parameter count is in eax.
145565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
145665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The displacement is used for skipping the frame pointer on the
145765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // stack. It is the offset of the last parameter (if any) relative
145865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // to the frame pointer.
145965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static const int kDisplacement = 1 * kPointerSize;
146065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
146165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the key is a smi.
146265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label slow;
14634668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ JumpIfNotSmi(edx, &slow, Label::kNear);
146465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
146565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if the calling frame is an arguments adaptor frame.
146683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label adaptor;
146765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
146865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset));
1469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
147083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(equal, &adaptor, Label::kNear);
147165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
147265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check index against formal parameters count limit passed in
147365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // through register eax. Use unsigned comparison to get negative
147465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // check for free.
1475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(edx, eax);
14764668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(above_equal, &slow, Label::kNear);
147765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
147865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Read the argument from the stack and return it.
147965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
148065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);  // Shifting code depends on these.
148165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ebx, Operand(ebp, eax, times_2, 0));
148265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ neg(edx);
148365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
148465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
148565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
148665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Arguments adaptor case: Check index against actual arguments
148765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // limit found in the arguments adaptor frame. Use unsigned
148865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // comparison to get negative check for free.
148965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&adaptor);
149065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
1491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(edx, ecx);
14924668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(above_equal, &slow, Label::kNear);
149365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
149465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Read the argument from the stack and return it.
149565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
149665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);  // Shifting code depends on these.
149765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ebx, Operand(ebx, ecx, times_2, 0));
149865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ neg(edx);
149965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
150065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
150165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
150265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Slow-case: Handle non-smi or out-of-bounds access to arguments
150365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // by calling the runtime system.
150465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow);
150565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(ebx);  // Return address.
150665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(edx);
150765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(ebx);
150865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
150965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
151065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
151165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
15127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
151365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esp[0] : return address
151465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esp[4] : number of parameters
151565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esp[8] : receiver displacement
15167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] : function
15177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Check if the calling frame is an arguments adaptor frame.
15197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label runtime;
15207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
15217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
1522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
15237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(not_equal, &runtime, Label::kNear);
15247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Patch the arguments.length and the parameters pointer.
15267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
15277b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), ecx);
15287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(edx, Operand(edx, ecx, times_2,
15297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org              StandardFrameConstants::kCallerSPOffset));
15307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), edx);
15317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&runtime);
15337b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
15347b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org}
153565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
15367b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
1538d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Isolate* isolate = masm->isolate();
1539d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
15407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] : return address
15417b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[4] : number of parameters (tagged)
15427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] : receiver displacement
15437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] : function
15447b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ebx = parameter count (tagged)
15467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ebx, Operand(esp, 1 * kPointerSize));
15477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Check if the calling frame is an arguments adaptor frame.
15497b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // TODO(rossberg): Factor out some of the bits that are shared with the other
15507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Generate* functions.
15517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label runtime;
15527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label adaptor_frame, try_allocate;
15537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
15547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
1555c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
15567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(equal, &adaptor_frame, Label::kNear);
15577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // No adaptor, parameter count = argument count.
15597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ecx, ebx);
15607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ jmp(&try_allocate, Label::kNear);
15617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // We have an adaptor frame. Patch the parameters pointer.
15637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&adaptor_frame);
15647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
15657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(edx, Operand(edx, ecx, times_2,
15667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org                      StandardFrameConstants::kCallerSPOffset));
15677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), edx);
15687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ebx = parameter count (tagged)
15707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ecx = argument count (tagged)
15717b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[4] = parameter count (tagged)
15727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] = address of receiver argument
15737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Compute the mapped parameter count = min(ebx, ecx) in ebx.
1574c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, ecx);
15757b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(less_equal, &try_allocate, Label::kNear);
15767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ebx, ecx);
15777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&try_allocate);
15797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15807b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Save mapped parameter count.
15817b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ push(ebx);
15827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15837b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Compute the sizes of backing store, parameter map, and arguments object.
15847b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // 1. Parameter map, has 2 extra words containing context and backing store.
15857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int kParameterMapHeaderSize =
15867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      FixedArray::kHeaderSize + 2 * kPointerSize;
15877b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label no_parameter_map;
1588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ebx, ebx);
15897b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(zero, &no_parameter_map, Label::kNear);
15907b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize));
15917b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&no_parameter_map);
15927b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15937b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // 2. Backing store.
15947b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
15957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // 3. Arguments object.
1597c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, Immediate(Heap::kArgumentsObjectSize));
15987b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
15997b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Do the allocation of all three objects in one go.
1600f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
16017b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16027b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // eax = address of new object(s) (tagged)
16037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ecx = argument count (tagged)
16047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] = mapped parameter count (tagged)
16057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] = parameter count (tagged)
16067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] = address of receiver argument
160746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Get the arguments boilerplate from the current native context into edi.
16087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label has_mapped_parameters, copy;
160946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
161046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset));
16117b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ebx, Operand(esp, 0 * kPointerSize));
1612c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ebx, ebx);
16137b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(not_zero, &has_mapped_parameters, Label::kNear);
16147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edi, Operand(edi,
16157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org         Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX)));
16167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ jmp(&copy, Label::kNear);
16177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&has_mapped_parameters);
16197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edi, Operand(edi,
16207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org            Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX)));
16217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&copy);
16227b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // eax = address of new object (tagged)
16247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ebx = mapped parameter count (tagged)
16257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ecx = argument count (tagged)
16267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // edi = address of boilerplate object (tagged)
16277b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] = mapped parameter count (tagged)
16287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] = parameter count (tagged)
16297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] = address of receiver argument
16307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Copy the JS object part.
16317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
16327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    __ mov(edx, FieldOperand(edi, i));
16337b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    __ mov(FieldOperand(eax, i), edx);
16347b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  }
16357b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
1636f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the callee in-object property.
16377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
16387b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edx, Operand(esp, 4 * kPointerSize));
16397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(eax, JSObject::kHeaderSize +
16407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org                      Heap::kArgumentsCalleeIndex * kPointerSize),
16417b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org         edx);
16427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Use the length (smi tagged) and set that as an in-object property too.
16447b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
16457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(eax, JSObject::kHeaderSize +
16467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org                      Heap::kArgumentsLengthIndex * kPointerSize),
16477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org         ecx);
16487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
1649f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the elements pointer in the allocated arguments object.
16507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // If we allocated a parameter map, edi will point there, otherwise to the
16517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // backing store.
16527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
16537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
16547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // eax = address of new object (tagged)
16567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ebx = mapped parameter count (tagged)
16577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ecx = argument count (tagged)
16587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // edi = address of parameter map or backing store (tagged)
16597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] = mapped parameter count (tagged)
16607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] = parameter count (tagged)
16617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] = address of receiver argument
16627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Free a register.
16637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ push(eax);
16647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Initialize parameter map. If there are no mapped arguments, we're done.
16667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label skip_parameter_map;
1667c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ebx, ebx);
16687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(zero, &skip_parameter_map);
16697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, FixedArray::kMapOffset),
1671d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org         Immediate(isolate->factory()->non_strict_arguments_elements_map()));
16727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2))));
16737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax);
16747b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi);
16757b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize));
16767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax);
16777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
16787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Copy the parameter slots and the holes in the arguments.
16797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // We need to fill in mapped_parameter_count slots. They index the context,
16807b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // where parameters are stored in reverse order, at
16817b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
16827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // The mapped parameter thus need to get indices
16837b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
16847b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
16857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // We loop from right to left.
16867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label parameters_loop, parameters_test;
16877b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ push(ecx);
16887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(eax, Operand(esp, 2 * kPointerSize));
16897b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
16907b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ add(ebx, Operand(esp, 4 * kPointerSize));
1691c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(ebx, eax);
1692d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ mov(ecx, isolate->factory()->the_hole_value());
16937b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edx, edi);
16947b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize));
16957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // eax = loop variable (tagged)
16967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ebx = mapping index (tagged)
16977b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ecx = the hole value
16987b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // edx = address of parameter map (tagged)
16997b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // edi = address of backing store (tagged)
17007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] = argument count (tagged)
17017b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[4] = address of new object (tagged)
17027b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] = mapped parameter count (tagged)
17037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[16] = parameter count (tagged)
17047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[20] = address of receiver argument
17057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ jmp(&parameters_test, Label::kNear);
17067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17077b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&parameters_loop);
1708c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(eax, Immediate(Smi::FromInt(1)));
17097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx);
17107b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx);
1711c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, Immediate(Smi::FromInt(1)));
17127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&parameters_test);
1713c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(eax, eax);
17147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(not_zero, &parameters_loop, Label::kNear);
17157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ pop(ecx);
17167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&skip_parameter_map);
17187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // ecx = argument count (tagged)
17207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // edi = address of backing store (tagged)
17217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] = address of new object (tagged)
17227b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[4] = mapped parameter count (tagged)
17237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] = parameter count (tagged)
17247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[16] = address of receiver argument
17257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Copy arguments header and remaining slots (if there are any).
17267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, FixedArray::kMapOffset),
1727d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org         Immediate(isolate->factory()->fixed_array_map()));
17287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
17297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  Label arguments_loop, arguments_test;
17317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(ebx, Operand(esp, 1 * kPointerSize));
17327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edx, Operand(esp, 4 * kPointerSize));
1733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edx, ebx);  // Is there a smarter way to do negative scaling?
1734c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edx, ebx);
17357b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ jmp(&arguments_test, Label::kNear);
17367b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&arguments_loop);
1738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edx, Immediate(kPointerSize));
17397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(eax, Operand(edx, 0));
17407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax);
1741c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, Immediate(Smi::FromInt(1)));
17427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&arguments_test);
1744c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, ecx);
17457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ j(less, &arguments_loop, Label::kNear);
17467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Restore.
17487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ pop(eax);  // Address of arguments object.
17497b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ pop(ebx);  // Parameter count.
17507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Return and remove the on-stack parameters.
17527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ ret(3 * kPointerSize);
17537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // Do the runtime call to allocate the arguments object.
17557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ bind(&runtime);
17567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ pop(eax);  // Remove saved parameter count.
17577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), ecx);  // Patch argument count.
175872204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
17597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org}
17607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
17627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
1763d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Isolate* isolate = masm->isolate();
1764d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
17657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[0] : return address
17667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[4] : number of parameters
17677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[8] : receiver displacement
17687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // esp[12] : function
176965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
177065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if the calling frame is an arguments adaptor frame.
177165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label adaptor_frame, try_allocate, runtime;
177265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
177365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset));
1774c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
17754668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(equal, &adaptor_frame, Label::kNear);
177665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
177765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the length from the frame.
177865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(esp, 1 * kPointerSize));
17794668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ jmp(&try_allocate, Label::kNear);
178065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
178165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Patch the arguments.length and the parameters pointer.
178265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&adaptor_frame);
178365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
178465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), ecx);
17857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(edx, Operand(edx, ecx, times_2,
17867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org                      StandardFrameConstants::kCallerSPOffset));
178765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), edx);
178865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
178965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Try the new space allocation. Start out with computing the size of
179065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // the arguments object and the elements array.
179183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label add_arguments_object;
179265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&try_allocate);
1793c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ecx, ecx);
179483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(zero, &add_arguments_object, Label::kNear);
179565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
179665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&add_arguments_object);
1797c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ecx, Immediate(Heap::kArgumentsObjectSizeStrict));
179865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
179965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do the allocation of both objects in one go.
1800f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
180165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
180246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  // Get the arguments boilerplate from the current native context.
180346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
180446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset));
18057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  const int offset =
18067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
18077b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ mov(edi, Operand(edi, offset));
180865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
180965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy the JS object part.
181065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
181165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(ebx, FieldOperand(edi, i));
181265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(FieldOperand(eax, i), ebx);
181365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
181465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
181565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the length (smi tagged) and set that as an in-object property too.
1816ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
181765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(esp, 1 * kPointerSize));
1818ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(FieldOperand(eax, JSObject::kHeaderSize +
18197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org                      Heap::kArgumentsLengthIndex * kPointerSize),
1820ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org         ecx);
182165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
182265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If there are no actual arguments, we're done.
182365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label done;
1824c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ecx, ecx);
18254668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(zero, &done, Label::kNear);
182665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
182765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the parameters pointer from the stack.
182865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, Operand(esp, 2 * kPointerSize));
182965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
1830f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the elements pointer in the allocated arguments object and
183165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // initialize the header in the elements fixed array.
18327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict));
183365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
183465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(edi, FixedArray::kMapOffset),
1835d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org         Immediate(isolate->factory()->fixed_array_map()));
1836ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
183765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
183865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Untag the length for the loop below.
183965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(ecx);
184065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
184165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy the fixed array slots.
184283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label loop;
184365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
184465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, Operand(edx, -1 * kPointerSize));  // Skip receiver.
184565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx);
1846c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edi, Immediate(kPointerSize));
1847c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edx, Immediate(kPointerSize));
184865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ dec(ecx);
184965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_zero, &loop);
185065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
185165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return and remove the on-stack parameters.
185265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
185365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(3 * kPointerSize);
185465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
185565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do the runtime call to allocate the arguments object.
185665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
18577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
185865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
185965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
186065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
186165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid RegExpExecStub::Generate(MacroAssembler* masm) {
186265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Just jump directly to runtime if native RegExp is not selected at compile
186365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // time or if regexp entry in generated code is turned off runtime switch or
186465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // at compilation.
186565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef V8_INTERPRETED_REGEXP
186665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
186765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#else  // V8_INTERPRETED_REGEXP
186865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
186965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack frame on entry.
187065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[0]: return address
187165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[4]: last_match_info (expected JSArray)
187265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[8]: previous index
187365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[12]: subject string
187465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[16]: JSRegExp object
187565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
187665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static const int kLastMatchInfoOffset = 1 * kPointerSize;
187765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static const int kPreviousIndexOffset = 2 * kPointerSize;
187865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static const int kSubjectOffset = 3 * kPointerSize;
187965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static const int kJSRegExpOffset = 4 * kPointerSize;
188065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
188171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  Label runtime;
188271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  Factory* factory = masm->isolate()->factory();
188365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
188465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Ensure that a RegExp stack is allocated.
188565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference address_of_regexp_stack_memory_address =
1886ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::address_of_regexp_stack_memory_address(
1887ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org          masm->isolate());
188865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference address_of_regexp_stack_memory_size =
1889ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::address_of_regexp_stack_memory_size(masm->isolate());
189065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
1891c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ebx, ebx);
18927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(zero, &runtime);
189365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
189465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the first argument is a JSRegExp object.
189565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, kJSRegExpOffset));
189665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
18977b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(eax, &runtime);
189865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
189965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, &runtime);
190071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
190165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the RegExp has been compiled (data contains a fixed array).
190265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
190365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (FLAG_debug_code) {
190465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ test(ecx, Immediate(kSmiTagMask));
1905594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(not_zero, kUnexpectedTypeForRegExpDataFixedArrayExpected);
190665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx);
1907594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
190865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
190965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
191065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: RegExp data (FixedArray)
191165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
191265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, FieldOperand(ecx, JSRegExp::kDataTagOffset));
1913c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, Immediate(Smi::FromInt(JSRegExp::IRREGEXP)));
191465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, &runtime);
191565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
191665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: RegExp data (FixedArray)
191765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the number of captures fit in the static offsets vector buffer.
191865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
191971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check (number_of_captures + 1) * 2 <= offsets vector size
192071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Or          number_of_captures * 2 <= offsets vector size - 2
192171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Multiplying by 2 comes for free since edx is smi-tagged.
192265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
192365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
192471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
192571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(edx, Isolate::kJSRegexpStaticOffsetsVectorSize - 2);
192665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(above, &runtime);
192765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
19284668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Reset offset for possibly sliced string.
19294668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ Set(edi, Immediate(0));
193065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, kSubjectOffset));
193171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfSmi(eax, &runtime);
193271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(edx, eax);  // Make a copy of the original subject string.
193365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
193465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
193571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
193671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // eax: subject string
193771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // edx: subject string
193871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // ebx: subject string instance type
193971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // ecx: RegExp data (FixedArray)
194071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Handle subject string according to its encoding and representation:
194171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (1) Sequential two byte?  If yes, go to (9).
194271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (2) Sequential one byte?  If yes, go to (6).
194371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (3) Anything but sequential or cons?  If yes, go to (7).
194471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (4) Cons string.  If the string is flat, replace subject with first string.
194571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  //     Otherwise bailout.
194671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (5a) Is subject sequential two byte?  If yes, go to (9).
194771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (5b) Is subject external?  If yes, go to (8).
194871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (6) One byte sequential.  Load regexp code for one byte.
194971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (E) Carry on.
195071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  /// [...]
195171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
195271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Deferred code at the end of the stub:
195371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (7) Not a long external string?  If yes, go to (10).
195471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (8) External string.  Make it, offset-wise, look like a sequential string.
195571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (8a) Is the external string one byte?  If yes, go to (6).
195671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (9) Two byte sequential.  Load regexp code for one byte. Go to (E).
195771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (10) Short external string or not a string?  If yes, bail out to runtime.
195871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (11) Sliced string.  Replace subject with parent. Go to (5a).
195971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
196071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
196171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org        external_string /* 8 */, check_underlying /* 5a */,
196271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org        not_seq_nor_cons /* 7 */, check_code /* E */,
196371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org        not_long_external /* 10 */;
196471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
196571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (1) Sequential two byte?  If yes, go to (9).
19661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ and_(ebx, kIsNotStringMask |
19671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org               kStringRepresentationMask |
19681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org               kStringEncodingMask |
19691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org               kShortExternalStringMask);
197065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
197171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(zero, &seq_two_byte_string);  // Go to (9).
197271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
197371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (2) Sequential one byte?  If yes, go to (6).
197471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Any other sequential string must be one byte.
19751b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ and_(ebx, Immediate(kIsNotStringMask |
19761b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                         kStringRepresentationMask |
19771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                         kShortExternalStringMask));
197871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(zero, &seq_one_byte_string, Label::kNear);  // Go to (6).
197971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
198071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (3) Anything but sequential or cons?  If yes, go to (7).
198171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // We check whether the subject string is a cons, since sequential strings
198271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // have already been covered.
198380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kConsStringTag < kExternalStringTag);
198480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
19851b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
19861b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1987c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, Immediate(kExternalStringTag));
198871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(greater_equal, &not_seq_nor_cons);  // Go to (7).
19891b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
199071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (4) Cons string.  Check that it's flat.
199171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Replace subject with first string and reload instance type.
19924668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ cmp(FieldOperand(eax, ConsString::kSecondOffset), factory->empty_string());
199365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, &runtime);
199465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
199571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&check_underlying);
199665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
199771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
199871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
199971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (5a) Is subject sequential two byte?  If yes, go to (9).
200071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ test_b(ebx, kStringRepresentationMask | kStringEncodingMask);
200165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
200271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(zero, &seq_two_byte_string);  // Go to (9).
200371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (5b) Is subject external?  If yes, go to (8).
200471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ test_b(ebx, kStringRepresentationMask);
200571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // The underlying external string is never a short external string.
200671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength);
200771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength);
200871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(not_zero, &external_string);  // Go to (8).
200971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
201071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // eax: sequential subject string (or look-alike, external string)
201171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // edx: original subject string
201265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: RegExp data (FixedArray)
201371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (6) One byte sequential.  Load regexp code for one byte.
201471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&seq_one_byte_string);
201571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Load previous index and check range before edx is overwritten.  We have
201671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // to use edx instead of eax here because it might have been only made to
201771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // look like a sequential string when it actually is an external string.
201871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(ebx, Operand(esp, kPreviousIndexOffset));
201971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfNotSmi(ebx, &runtime);
202071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(ebx, FieldOperand(edx, String::kLengthOffset));
202171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(above_equal, &runtime);
202265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
202371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ Set(ecx, Immediate(1));  // Type is one byte.
202465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
202571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (E) Carry on.  String handling is done.
202665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&check_code);
202771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // edx: irregexp code
202865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the irregexp code has been generated for the actual string
202965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // encoding. If it has, the field contains a code object otherwise it contains
2030ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  // a smi (code flushing support).
2031ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org  __ JumpIfSmi(edx, &runtime);
203265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
203365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: subject string
203471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // ebx: previous index (smi)
203565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: code
20362efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // ecx: encoding of subject string (1 if ASCII, 0 if two_byte);
203765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // All checks done. Now push arguments for native regexp code.
20387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
20397979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->regexp_entry_native(), 1);
204065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2041ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Isolates: note we add an additional parameter here (isolate pointer).
204215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  static const int kRegExpExecuteArguments = 9;
204349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ EnterApiExitFrame(kRegExpExecuteArguments);
204465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
204515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 9: Pass current isolate address.
204615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(Operand(esp, 8 * kPointerSize),
204732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      Immediate(ExternalReference::isolate_address(masm->isolate())));
2048ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
204915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 8: Indicate that this is a direct call from JavaScript.
205015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(Operand(esp, 7 * kPointerSize), Immediate(1));
205165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
205215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 7: Start (high end) of backtracking stack memory area.
20534668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address));
20544668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size));
205515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(Operand(esp, 6 * kPointerSize), esi);
205615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
205715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Argument 6: Set the number of capture registers to zero to force global
205815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // regexps to behave as non-global.  This does not affect non-global regexps.
205915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(Operand(esp, 5 * kPointerSize), Immediate(0));
206065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
206165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Argument 5: static offsets vector buffer.
206265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 4 * kPointerSize),
2063ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org         Immediate(ExternalReference::address_of_static_offsets_vector(
2064ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org             masm->isolate())));
206565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
20664668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Argument 2: Previous index.
206771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ SmiUntag(ebx);
20684668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), ebx);
20694668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
20704668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Argument 1: Original subject string.
20714668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // The original subject is in the previous stack frame. Therefore we have to
20724668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // use ebp, which points exactly to one pointer size below the previous esp.
20734668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // (Because creating a new stack frame pushes the previous ebp onto the stack
20744668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // and thereby moves up esp by one kPointerSize.)
20754668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ mov(esi, Operand(ebp, kSubjectOffset + kPointerSize));
20764668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ mov(Operand(esp, 0 * kPointerSize), esi);
20774668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
20784668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // esi: original subject string
20794668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // eax: underlying subject string
20804668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // ebx: previous index
20812efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // ecx: encoding of subject string (1 if ASCII 0 if two_byte);
20824668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // edx: code
208365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Argument 4: End of string data
208465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Argument 3: Start of string data
20854668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Prepare start and end index of the input.
20864668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Load the length from the original sliced string if that is the case.
20874668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ mov(esi, FieldOperand(esi, String::kLengthOffset));
2088c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(esi, edi);  // Calculate input end wrt offset.
20894668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ SmiUntag(edi);
2090c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, edi);  // Calculate input start wrt offset.
20914668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
20924668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // ebx: start index of the input string
20934668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // esi: end index of the input string
209483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label setup_two_byte, setup_rest;
2095c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ecx, ecx);
209683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(zero, &setup_two_byte, Label::kNear);
20974668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ SmiUntag(esi);
2098fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ lea(ecx, FieldOperand(eax, esi, times_1, SeqOneByteString::kHeaderSize));
209965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Argument 4.
2100fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqOneByteString::kHeaderSize));
210165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), ecx);  // Argument 3.
210283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&setup_rest, Label::kNear);
210365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
210465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&setup_two_byte);
210565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
21064668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);  // esi is smi (powered by 2).
21074668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ lea(ecx, FieldOperand(eax, esi, times_1, SeqTwoByteString::kHeaderSize));
210865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Argument 4.
210965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize));
211065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), ecx);  // Argument 3.
211165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
211265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&setup_rest);
211365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
211465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate the code entry and call it.
2115c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2116c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ call(edx);
211749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
211849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Drop arguments and come back to JS mode.
2119528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ LeaveApiExitFrame(true);
212065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
212165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check the result.
212265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label success;
212315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ cmp(eax, 1);
212415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // We expect exactly one result since we force the called regexp to behave
212515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // as non-global.
21267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(equal, &success);
212765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label failure;
212865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
21297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(equal, &failure);
213065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
213165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If not exception it can only be retry. Handle that in the runtime system.
213265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, &runtime);
213365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result must now be exception. If there is no pending exception already a
213465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // stack overflow (on the backtrack stack) was detected in RegExp code but
213565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // haven't created the exception yet. Handle that in the runtime system.
213665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
213783e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
2138ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                      masm->isolate());
2139c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
214049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ mov(eax, Operand::StaticVariable(pending_exception));
2141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(edx, eax);
214265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(equal, &runtime);
214349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // For exception, throw the exception again.
214449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
214549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Clear the pending exception variable.
214649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ mov(Operand::StaticVariable(pending_exception), edx);
214749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
214849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Special handling of termination exceptions which are uncatchable
214949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // by javascript code.
21507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(eax, factory->termination_exception());
215149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  Label throw_termination_exception;
21524668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(equal, &throw_termination_exception, Label::kNear);
215349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
215449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Handle normal exception by following handler chain.
215549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ Throw(eax);
215649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
215749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  __ bind(&throw_termination_exception);
215865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ ThrowUncatchable(eax);
215949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
216065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&failure);
216149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // For failure to match, return null.
2162c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(eax, factory->null_value());
216365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(4 * kPointerSize);
216465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
216565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load RegExp data.
216665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&success);
216765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, kJSRegExpOffset));
216865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
216965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, FieldOperand(ecx, JSRegExp::kIrregexpCaptureCountOffset));
217065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate number of capture registers (number_of_captures + 1) * 2.
217165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
217265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
2173c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edx, Immediate(2));  // edx was a smi.
217465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
217565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: Number of capture registers
217665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load last_match_info which is still known to be a fast case JSArray.
217771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check that the fourth object is a JSArray object.
217865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, kLastMatchInfoOffset));
217971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfSmi(eax, &runtime);
218071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
218171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(not_equal, &runtime);
218271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check that the JSArray is in fast case.
218365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset));
218471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset));
218571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(eax, factory->fixed_array_map());
218671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(not_equal, &runtime);
218771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Check that the last match info has space for the capture registers and the
218871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // additional information.
218971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
219071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ SmiUntag(eax);
219171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ sub(eax, Immediate(RegExpImpl::kLastMatchOverhead));
219271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(edx, eax);
219371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(greater, &runtime);
219465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
219565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: last_match_info backing store (FixedArray)
219665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: number of capture registers
219765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Store the capture count.
219865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiTag(edx);  // Number of capture registers to smi.
219965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ebx, RegExpImpl::kLastCaptureCountOffset), edx);
220065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(edx);  // Number of capture registers back from smi.
220165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Store last subject and last input.
220265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, kSubjectOffset));
220371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(ecx, eax);
220465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax);
2205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ RecordWriteField(ebx,
2206c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      RegExpImpl::kLastSubjectOffset,
2207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      eax,
2208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      edi,
2209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      kDontSaveFPRegs);
221071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(eax, ecx);
221165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax);
2212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ RecordWriteField(ebx,
2213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      RegExpImpl::kLastInputOffset,
2214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      eax,
2215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      edi,
2216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                      kDontSaveFPRegs);
221765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
221865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Get the static offsets vector filled by the native regexp code.
221965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference address_of_static_offsets_vector =
2220ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::address_of_static_offsets_vector(masm->isolate());
222165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Immediate(address_of_static_offsets_vector));
222265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
222365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: last_match_info backing store (FixedArray)
222465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: offsets vector
222565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: number of capture registers
222683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label next_capture, done;
222765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Capture register counter starts from number of capture registers and
222865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // counts down until wraping after zero.
222965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&next_capture);
2230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edx, Immediate(1));
223183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(negative, &done, Label::kNear);
223265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Read the value from the static offsets vector buffer.
223365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, Operand(ecx, edx, times_int_size, 0));
223465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiTag(edi);
223565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Store the smi value in the last match info.
223665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ebx,
223765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      edx,
223865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      times_pointer_size,
223965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      RegExpImpl::kFirstCaptureOffset),
224065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                      edi);
224165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&next_capture);
224265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
224365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
224465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Return last match info.
224565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, kLastMatchInfoOffset));
224665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(4 * kPointerSize);
224765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
224871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Do the runtime call to execute the regexp.
224971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&runtime);
225071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
225171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
225271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Deferred code for string handling.
225371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (7) Not a long external string?  If yes, go to (10).
225471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&not_seq_nor_cons);
225571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Compare flags are still set from (3).
225671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(greater, &not_long_external, Label::kNear);  // Go to (10).
225771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
225871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (8) External string.  Short external strings have been ruled out.
22591b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ bind(&external_string);
226071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Reload instance type.
22611b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
22621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
22631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (FLAG_debug_code) {
22641b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Assert that we do not have a cons or slice (indirect strings) here.
22651b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // Sequential strings have already been ruled out.
22661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    __ test_b(ebx, kIsIndirectStringMask);
2267594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(zero, kExternalStringExpectedButNotFound);
22681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
22691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
22701b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Move the pointer so that offset-wise, it looks like a sequential string.
2271fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
22721b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ sub(eax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
22731b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  STATIC_ASSERT(kTwoByteStringTag == 0);
227471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (8a) Is the external string one byte?  If yes, go to (6).
22751b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  __ test_b(ebx, kStringEncodingMask);
227671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(not_zero, &seq_one_byte_string);  // Goto (6).
22771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
227871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // eax: sequential subject string (or look-alike, external string)
227971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // edx: original subject string
228071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // ecx: RegExp data (FixedArray)
228171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (9) Two byte sequential.  Load regexp code for one byte. Go to (E).
228271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&seq_two_byte_string);
228371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Load previous index and check range before edx is overwritten.  We have
228471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // to use edx instead of eax here because it might have been only made to
228571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // look like a sequential string when it actually is an external string.
228671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(ebx, Operand(esp, kPreviousIndexOffset));
228771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ JumpIfNotSmi(ebx, &runtime);
228871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ cmp(ebx, FieldOperand(edx, String::kLengthOffset));
228971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(above_equal, &runtime);
229071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset));
229171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ Set(ecx, Immediate(0));  // Type is two byte.
229271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ jmp(&check_code);  // Go to (E).
229371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
229471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (10) Not a string or a short external string?  If yes, bail out to runtime.
229571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ bind(&not_long_external);
229671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Catch non-string subject or short external string.
229771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
229871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ test(ebx, Immediate(kIsNotStringMask | kShortExternalStringTag));
229971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ j(not_zero, &runtime);
230071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org
230171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // (11) Sliced string.  Replace subject with parent.  Go to (5a).
230271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  // Load offset into edi and replace subject string with parent.
230371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(edi, FieldOperand(eax, SlicedString::kOffsetOffset));
230471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ mov(eax, FieldOperand(eax, SlicedString::kParentOffset));
230571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org  __ jmp(&check_underlying);  // Go to (5a).
230665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif  // V8_INTERPRETED_REGEXP
230765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
230865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
230965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2310a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid RegExpConstructResultStub::Generate(MacroAssembler* masm) {
2311a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kMaxInlineLength = 100;
2312a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label slowcase;
231383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
2314a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ebx, Operand(esp, kPointerSize * 3));
23157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(ebx, &slowcase);
2316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, Immediate(Smi::FromInt(kMaxInlineLength)));
2317a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ j(above, &slowcase);
2318a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Smi-tagging is equivalent to multiplying by 2.
2319a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  STATIC_ASSERT(kSmiTag == 0);
2320a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
2321a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Allocate RegExpResult followed by FixedArray with size in ebx.
2322a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // JSArray:   [Map][empty properties][Elements][Length-smi][index][input]
2323a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Elements:  [Map][Length][..elements..]
2324f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize,
2325f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              times_pointer_size,
2326f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              ebx,  // In: Number of elements as a smi
2327f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              REGISTER_VALUE_IS_SMI,
2328f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              eax,  // Out: Start of allocation (tagged).
2329f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              ecx,  // Out: End of allocation.
2330f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              edx,  // Scratch register
2331f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              &slowcase,
2332f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org              TAG_OBJECT);
2333a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // eax: Start of allocated area, object-tagged.
2334a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2335a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set JSArray map to global.regexp_result_map().
2336a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set empty properties FixedArray.
2337a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set elements to point to FixedArray allocated right after the JSArray.
2338a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Interleave operations for better latency.
233946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(edx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
23407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
23417979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ mov(ecx, Immediate(factory->empty_fixed_array()));
2342a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ lea(ebx, Operand(eax, JSRegExpResult::kSize));
234346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __ mov(edx, FieldOperand(edx, GlobalObject::kNativeContextOffset));
2344a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx);
2345a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx);
2346a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX));
2347a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx);
2348a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2349a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set input, index and length fields from arguments.
2350a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ecx, Operand(esp, kPointerSize * 1));
2351a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(eax, JSRegExpResult::kInputOffset), ecx);
2352a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ecx, Operand(esp, kPointerSize * 2));
2353a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(eax, JSRegExpResult::kIndexOffset), ecx);
2354a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ecx, Operand(esp, kPointerSize * 3));
2355a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx);
2356a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2357a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Fill out the elements FixedArray.
2358a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // eax: JSArray.
2359a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // ebx: FixedArray.
2360a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // ecx: Number of elements in array, as smi.
2361a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2362a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set map.
2363a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(ebx, HeapObject::kMapOffset),
23647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org         Immediate(factory->fixed_array_map()));
2365a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Set length.
2366a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx);
236756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Fill contents of fixed-array with undefined.
2368a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ SmiUntag(ecx);
236956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  __ mov(edx, Immediate(factory->undefined_value()));
2370a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize));
237156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Fill fixed array elements with undefined.
2372a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // eax: JSArray.
2373a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // ecx: Number of elements to fill.
2374a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // ebx: Start of elements in FixedArray.
237556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // edx: undefined.
2376a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label loop;
2377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ecx, ecx);
2378a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&loop);
237983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(less_equal, &done, Label::kNear);  // Jump if ecx is negative or zero.
2380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(ecx, Immediate(1));
2381a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(ebx, ecx, times_pointer_size, 0), edx);
2382a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ jmp(&loop);
2383a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2384a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&done);
2385a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ret(3 * kPointerSize);
2386a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2387a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&slowcase);
2388a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
2389a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
2390a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2391a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
239265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic int NegativeComparisonResult(Condition cc) {
239365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(cc != equal);
239465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT((cc == less) || (cc == less_equal)
239565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      || (cc == greater) || (cc == greater_equal));
239665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  return (cc == greater || cc == greater_equal) ? LESS : GREATER;
239765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
239865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
239965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2400fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgstatic void CheckInputType(MacroAssembler* masm,
2401fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                           Register input,
2402fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                           CompareIC::State expected,
2403fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                           Label* fail) {
2404fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label ok;
2405fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (expected == CompareIC::SMI) {
2406fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(input, fail);
24078432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  } else if (expected == CompareIC::NUMBER) {
2408fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(input, &ok);
2409fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(FieldOperand(input, HeapObject::kMapOffset),
2410fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org           Immediate(masm->isolate()->factory()->heap_number_map()));
2411fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(not_equal, fail);
2412fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
24134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // We could be strict about internalized/non-internalized here, but as long as
2414fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // hydrogen doesn't care, the stub doesn't have to care either.
2415fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&ok);
2416fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}
2417fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2418fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
24194a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgstatic void BranchIfNotInternalizedString(MacroAssembler* masm,
24204a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                          Label* label,
24214a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                          Register object,
24224a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                                          Register scratch) {
2423fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ JumpIfSmi(object, label);
2424fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset));
2425fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
2426ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2427ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
2428ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ j(not_zero, label);
2429fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org}
2430fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2431fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2432fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
24334668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Label check_unequal_objects;
2434fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Condition cc = GetCondition();
243565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2436fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label miss;
2437fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  CheckInputType(masm, edx, left_, &miss);
2438fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  CheckInputType(masm, eax, right_, &miss);
2439fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2440fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // Compare two smis.
2441fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label non_smi, smi_done;
2442fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ mov(ecx, edx);
2443fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ or_(ecx, eax);
2444fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ JumpIfNotSmi(ecx, &non_smi, Label::kNear);
2445fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ sub(edx, eax);  // Return on the result of the subtraction.
2446fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ j(no_overflow, &smi_done, Label::kNear);
2447fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ not_(edx);  // Correct sign in case of overflow. edx is never 0 here.
2448fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&smi_done);
2449fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ mov(eax, edx);
2450fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ ret(0);
2451fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&non_smi);
2452d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
245365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // NOTICE! This code is only reached after a smi-fast-case check, so
245465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // it is certain that at least one operand isn't a smi.
245565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
245665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Identical objects can be compared fast, but there are some tricky cases
245765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // for NaN and undefined.
2458f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  Label generic_heap_number_comparison;
245965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  {
246065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label not_identical;
2461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(eax, edx);
246265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(not_equal, &not_identical);
246365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2464fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    if (cc != equal) {
246565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      // Check for undefined.  undefined OP undefined is false even though
246665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      // undefined == undefined.
246783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label check_for_nan;
24687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      __ cmp(edx, masm->isolate()->factory()->undefined_value());
246983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      __ j(not_equal, &check_for_nan, Label::kNear);
2470fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
247165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ ret(0);
247265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ bind(&check_for_nan);
247365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
247465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2475f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    // Test for NaN. Compare heap numbers in a general way,
2476f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    // to hanlde NaNs correctly.
2477fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2478fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org           Immediate(masm->isolate()->factory()->heap_number_map()));
2479f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    __ j(equal, &generic_heap_number_comparison, Label::kNear);
2480fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    if (cc != equal) {
2481fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      // Call runtime on identical JSObjects.  Otherwise return equal.
2482fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2483fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      __ j(above_equal, &not_identical);
2484fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    }
2485fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
2486fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ret(0);
2487fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
248865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
248965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&not_identical);
249065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
249165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
249265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Strict equality can quickly decide whether objects are equal.
249365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Non-strict object equality is slower, so it is handled later in the stub.
2494fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == equal && strict()) {
249565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Label slow;  // Fallthrough label.
249683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label not_smis;
249765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If we're doing a strict equality comparison, we don't have to do
249865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // type conversion, so we generate code to do fast comparison for objects
249965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // and oddballs. Non-smi numbers and strings still go through the usual
250065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // slow-case code.
250165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If either is a Smi (we know that not both are), then they can only
250265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // be equal if the other is a HeapNumber. If so, use the slow case.
250365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kSmiTag == 0);
250465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    ASSERT_EQ(0, Smi::FromInt(0));
250565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(ecx, Immediate(kSmiTagMask));
2506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ and_(ecx, eax);
2507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ test(ecx, edx);
250883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(not_zero, &not_smis, Label::kNear);
250965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // One operand is a smi.
251065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
251165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check whether the non-smi is a heap number.
251265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kSmiTagMask == 1);
251365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // ecx still holds eax & kSmiTag, which is either zero or one.
2514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(ecx, Immediate(0x01));
251565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(ebx, edx);
2516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ xor_(ebx, eax);
2517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ and_(ebx, ecx);  // ebx holds either 0 or eax ^ edx.
2518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ xor_(ebx, eax);
251965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // if eax was smi, ebx is now edx, else eax.
252065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
252165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check if the non-smi operand is a heap number.
252265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
25237979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org           Immediate(masm->isolate()->factory()->heap_number_map()));
252465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If heap number, handle it in the slow case.
25254668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    __ j(equal, &slow, Label::kNear);
252665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Return non-equal (ebx is not zero)
252765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(eax, ebx);
252865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ret(0);
252965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
253065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&not_smis);
253165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If either operand is a JSObject or an oddball value, then they are not
253265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // equal since their pointers are different
253365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // There is no test for undetectability in strict equality.
253465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
253565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Get the type of the first operand.
253665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If the first object is a JS object, we have done pointer comparison.
253783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label first_non_object;
2538d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
2539d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
254083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(below, &first_non_object, Label::kNear);
254165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
254265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Return non-zero (eax is not zero)
254383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label return_not_equal;
254465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kHeapObjectTag != 0);
254565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&return_not_equal);
254665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ret(0);
254765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
254865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&first_non_object);
254965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for oddballs: true, false, null, undefined.
255065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CmpInstanceType(ecx, ODDBALL_TYPE);
255165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(equal, &return_not_equal);
255265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2553d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ecx);
255465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(above_equal, &return_not_equal);
255565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
255665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for oddballs: true, false, null, undefined.
255765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CmpInstanceType(ecx, ODDBALL_TYPE);
255865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(equal, &return_not_equal);
255965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
256065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Fall through to the general case.
256165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&slow);
256265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
256365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
256465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Generate the number comparison code.
2565fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label non_number_comparison;
2566fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  Label unordered;
2567f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ bind(&generic_heap_number_comparison);
2568fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (CpuFeatures::IsSupported(SSE2)) {
2569750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope use_sse2(masm, SSE2);
2570750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope use_cmov(masm, CMOV);
257165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2572fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
2573fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ucomisd(xmm0, xmm1);
257465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2575fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Don't base result on EFLAGS when a NaN is involved.
2576fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(parity_even, &unordered, Label::kNear);
2577fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Return a result of -1, 0, or 1, based on EFLAGS.
2578fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(eax, 0);  // equal
2579fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(ecx, Immediate(Smi::FromInt(1)));
2580fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmov(above, eax, ecx);
2581fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(ecx, Immediate(Smi::FromInt(-1)));
2582fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmov(below, eax, ecx);
2583fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ret(0);
2584fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  } else {
2585fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    FloatingPointHelper::CheckFloatOperands(
2586fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org        masm, &non_number_comparison, ebx);
2587fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    FloatingPointHelper::LoadFloatOperand(masm, eax);
2588fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    FloatingPointHelper::LoadFloatOperand(masm, edx);
2589fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ FCmp();
259065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2591fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Don't base result on EFLAGS when a NaN is involved.
2592fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(parity_even, &unordered, Label::kNear);
259365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2594fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    Label below_label, above_label;
2595fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Return a result of -1, 0, or 1, based on EFLAGS.
2596fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(below, &below_label, Label::kNear);
2597fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(above, &above_label, Label::kNear);
259865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2599fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ Set(eax, Immediate(0));
2600fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ret(0);
260165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2602fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&below_label);
2603fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(eax, Immediate(Smi::FromInt(-1)));
2604fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ ret(0);
260565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2606fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&above_label);
2607fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(eax, Immediate(Smi::FromInt(1)));
260865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ret(0);
2609fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
261065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2611fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // If one of the numbers was NaN, then the result is always false.
2612fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // The cc is never not-equal.
2613fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&unordered);
2614fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(cc != not_equal);
2615fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == less || cc == less_equal) {
2616fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(eax, Immediate(Smi::FromInt(1)));
2617fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  } else {
2618fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(eax, Immediate(Smi::FromInt(-1)));
261965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
2620fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ ret(0);
2621fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
2622fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // The number comparison code did not provide a valid result.
2623fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&non_number_comparison);
262465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
26254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Fast negative check for internalized-to-internalized equality.
262665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label check_for_strings;
2627fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == equal) {
26284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    BranchIfNotInternalizedString(masm, &check_for_strings, eax, ecx);
26294a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    BranchIfNotInternalizedString(masm, &check_for_strings, edx, ecx);
263065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
263165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // We've already checked for object identity, so if both operands
26324a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // are internalized they aren't equal. Register eax already holds a
263365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // non-zero value, which indicates not equal, so just return.
263465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ret(0);
263565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
263665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
263765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&check_for_strings);
263865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
263965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx,
264065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                         &check_unequal_objects);
264165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
26422efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Inline comparison of ASCII strings.
2643fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == equal) {
26441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    StringCompareStub::GenerateFlatAsciiStringEquals(masm,
264565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                     edx,
264665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                     eax,
264765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                     ecx,
26481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                     ebx);
26491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  } else {
26501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
26511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       edx,
26521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       eax,
26531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       ecx,
26541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       ebx,
26551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                       edi);
26561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
265765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef DEBUG
2658594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallThroughFromStringComparison);
265965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif
266065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
266165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&check_unequal_objects);
2662fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == equal && !strict()) {
266365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Non-strict equality.  Objects are unequal if
266465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // they are both JSObjects and not undetectable,
266565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // and their pointers are different.
266683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label not_both_objects;
266783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label return_unequal;
266865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // At most one is a smi, so we can test for smi by adding the two.
266965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // A smi plus a heap object has the low bit set, a heap object plus
267065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // a heap object has the low bit clear.
267165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kSmiTag == 0);
267265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    STATIC_ASSERT(kSmiTagMask == 1);
267365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ lea(ecx, Operand(eax, edx, times_1, 0));
267465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ test(ecx, Immediate(kSmiTagMask));
267583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(not_zero, &not_both_objects, Label::kNear);
2676d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
267783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(below, &not_both_objects, Label::kNear);
2678d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ebx);
267983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(below, &not_both_objects, Label::kNear);
268065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // We do not bail out after this point.  Both are JSObjects, and
268165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // they are equal if and only if both are undetectable.
268265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // The and of the undetectable flags is 1 if and only if they are equal.
268365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
268465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org              1 << Map::kIsUndetectable);
268583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(zero, &return_unequal, Label::kNear);
268665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
268765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org              1 << Map::kIsUndetectable);
268883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(zero, &return_unequal, Label::kNear);
268965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // The objects are both undetectable, so they both compare as the value
269065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // undefined, and are equal.
269165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Set(eax, Immediate(EQUAL));
269265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&return_unequal);
269365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Return non-equal by returning the non-zero object pointer in eax,
269465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // or return equal if we fell through to here.
269565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ ret(0);  // rax, rdx were pushed
269665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&not_both_objects);
269765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
269865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
269965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Push arguments below the return address.
270065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(ecx);
270165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(edx);
270265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(eax);
270365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
270465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Figure out which native to call and setup the arguments.
270565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Builtins::JavaScript builtin;
2706fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (cc == equal) {
2707fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
270865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
270965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    builtin = Builtins::COMPARE;
2710fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
271165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
271265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
271365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Restore return address on the stack.
271465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(ecx);
271565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
271665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
271765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // tagged as a small integer.
271865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ InvokeBuiltin(builtin, JUMP_FUNCTION);
271965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2720fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ bind(&miss);
2721fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  GenerateMiss(masm);
272265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
272365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
272465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
27254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgstatic void GenerateRecordCallTarget(MacroAssembler* masm) {
27264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Cache the called function in a global property cell.  Cache states
27274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // are uninitialized, monomorphic (indicated by a JSFunction), and
27284a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // megamorphic.
2729528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  // eax : number of arguments to the construct function
27304a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // ebx : cache cell for call target
27314a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // edi : the function to call
27324a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Isolate* isolate = masm->isolate();
27334a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label initialize, done, miss, megamorphic, not_array_function;
27344a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
27354a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Load the cache state into ecx.
273641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
27374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
27384a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // A monomorphic cache hit or an already megamorphic state: invoke the
27394a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // function without changing the state.
27404a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(ecx, edi);
27414a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ j(equal, &done);
27424a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
27434a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ j(equal, &done);
27444a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2745bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // If we came here, we need to see if we are the array function.
2746bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // If we didn't have a matching function, and we didn't find the megamorph
2747bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // sentinel, then we have in the cell either some other function or an
2748bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // AllocationSite. Do a map check on the object in ecx.
2749528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Handle<Map> allocation_site_map =
2750528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      masm->isolate()->factory()->allocation_site_map();
2751bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map));
2752bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ j(not_equal, &miss);
27531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
27544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Load the global or builtins object from the current context
27554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadGlobalContext(ecx);
27564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Make sure the function is the Array() function
27574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(edi, Operand(ecx,
27584a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                      Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
27594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ j(not_equal, &megamorphic);
27604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ jmp(&done);
27614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
27624a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&miss);
27634a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
27644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
27654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // megamorphic.
27664a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(ecx, Immediate(TypeFeedbackCells::UninitializedSentinel(isolate)));
27674a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ j(equal, &initialize);
27684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // MegamorphicSentinel is an immortal immovable object (undefined) so no
27694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // write-barrier is needed.
27704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&megamorphic);
277141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ mov(FieldOperand(ebx, Cell::kValueOffset),
27724a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org         Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
27734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ jmp(&done, Label::kNear);
27744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
27754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // An uninitialized cache is patched with the function or sentinel to
27764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // indicate the ElementsKind if function is the Array constructor.
27774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&initialize);
27784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadGlobalContext(ecx);
27794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Make sure the function is the Array() function
27804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(edi, Operand(ecx,
27814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                      Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
27824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ j(not_equal, &not_array_function);
27834a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
2784bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // The target function is the Array constructor,
2785bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Create an AllocationSite if we don't already have it, store it in the cell
2786bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  {
2787bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
2788bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
2789528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    // Arguments register must be smi-tagged to call out.
2790662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    __ SmiTag(eax);
2791bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ push(eax);
2792bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ push(edi);
2793bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ push(ebx);
2794bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
2795bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    CreateAllocationSiteStub create_stub;
2796bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ CallStub(&create_stub);
2797bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
2798bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ pop(ebx);
2799bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ pop(edi);
2800bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    __ pop(eax);
2801662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    __ SmiUntag(eax);
2802bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
28034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ jmp(&done);
28044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
28054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&not_array_function);
280641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ mov(FieldOperand(ebx, Cell::kValueOffset), edi);
28074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // No need for a write barrier here - cells are rescanned.
28084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
28094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&done);
28104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
28114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
28124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
281365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CallFunctionStub::Generate(MacroAssembler* masm) {
2814fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // ebx : cache cell for call target
2815c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  // edi : the function to call
2816c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Isolate* isolate = masm->isolate();
281734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  Label slow, non_function;
281865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
281940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // The receiver might implicitly be the global object. This is
282040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // indicated by passing the hole as the receiver to the call
282140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  // function stub.
282240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (ReceiverMightBeImplicit()) {
2823c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label receiver_ok;
282465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Get the receiver from the stack.
282565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // +1 ~ return address
282665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize));
282740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    // Call as function is indicated with the hole.
2828c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(eax, isolate->factory()->the_hole_value());
2829c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ j(not_equal, &receiver_ok, Label::kNear);
283040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    // Patch the receiver on the stack with the global receiver object.
2831fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ mov(ecx, GlobalObjectOperand());
2832fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
2833fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    __ mov(Operand(esp, (argc_ + 1) * kPointerSize), ecx);
2834c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&receiver_ok);
283565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
283665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
283765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the function really is a JavaScript function.
283834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ JumpIfSmi(edi, &non_function);
283965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Goto slow case if we do not have a function.
284065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
28417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(not_equal, &slow);
284265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2843c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (RecordCallTarget()) {
28441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    GenerateRecordCallTarget(masm);
2845c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
2846c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
284765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fast-case: Just invoke the function.
284865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ParameterCount actual(argc_);
284940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
285040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  if (ReceiverMightBeImplicit()) {
285140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    Label call_as_function;
2852c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(eax, isolate->factory()->the_hole_value());
285340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ j(equal, &call_as_function);
2854d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ InvokeFunction(edi,
2855d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      actual,
2856d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      JUMP_FUNCTION,
2857d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      NullCallWrapper(),
2858d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org                      CALL_AS_METHOD);
285940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ bind(&call_as_function);
286040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  }
286140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ InvokeFunction(edi,
286240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    actual,
286340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    JUMP_FUNCTION,
286440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    NullCallWrapper(),
286540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org                    CALL_AS_FUNCTION);
286665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
286765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Slow-case: Non-function called.
286865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow);
2869c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (RecordCallTarget()) {
2870c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // If there is a call target cache, mark it megamorphic in the
2871fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    // non-function case.  MegamorphicSentinel is an immortal immovable
2872fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org    // object (undefined) so no write barrier is needed.
287341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    __ mov(FieldOperand(ebx, Cell::kValueOffset),
2874fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org           Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
2875c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
287634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  // Check for function proxy.
287734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
287834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ j(not_equal, &non_function);
287934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ pop(ecx);
288034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ push(edi);  // put proxy as additional argument under return address
288134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ push(ecx);
288234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ Set(eax, Immediate(argc_ + 1));
288334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ Set(ebx, Immediate(0));
288434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ SetCallKind(ecx, CALL_AS_FUNCTION);
288534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
288634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  {
2887c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
288834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org    __ jmp(adaptor, RelocInfo::CODE_TARGET);
288934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  }
289034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org
289165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
289265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // of the original receiver from the call site).
289334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ bind(&non_function);
289465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi);
289565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Set(eax, Immediate(argc_));
289665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Set(ebx, Immediate(0));
289734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org  __ SetCallKind(ecx, CALL_AS_METHOD);
289865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
2899c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
290065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(adaptor, RelocInfo::CODE_TARGET);
290165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
290265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
290365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
2904fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgvoid CallConstructStub::Generate(MacroAssembler* masm) {
2905fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // eax : number of arguments
2906fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // ebx : cache cell for call target
2907fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // edi : constructor function
2908fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Label slow, non_function_call;
2909fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2910fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Check that function is not a smi.
2911fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ JumpIfSmi(edi, &non_function_call);
2912fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Check that function is a JSFunction.
2913fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2914fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ j(not_equal, &slow);
2915fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2916fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  if (RecordCallTarget()) {
29171510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    GenerateRecordCallTarget(masm);
2918fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  }
2919fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2920fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Jump to the function-specific construct stub.
29211510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Register jmp_reg = ecx;
29224a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
29234a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(jmp_reg, FieldOperand(jmp_reg,
29244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                               SharedFunctionInfo::kConstructStubOffset));
29254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize));
29264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ jmp(jmp_reg);
2927fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2928fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // edi: called object
2929fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // eax: number of arguments
2930fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // ecx: object map
2931fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Label do_call;
2932fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ bind(&slow);
2933fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2934fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ j(not_equal, &non_function_call);
2935fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
2936fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ jmp(&do_call);
2937fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2938fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ bind(&non_function_call);
2939fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
2940fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ bind(&do_call);
2941fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Set expected number of arguments to zero (not changing eax).
2942fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ Set(ebx, Immediate(0));
2943fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  Handle<Code> arguments_adaptor =
2944fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org      masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
2945fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ SetCallKind(ecx, CALL_AS_METHOD);
2946fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
2947fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org}
2948fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2949fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
29504d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.orgbool CEntryStub::NeedsImmovableCode() {
29514d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org  return false;
29524d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org}
29534d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
29544d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
29558432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
29568432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  CEntryStub::GenerateAheadOfTime(isolate);
29578432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2958e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2959c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // It is important that the store buffer overflow stubs are generated first.
29601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2961bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2962182d2db4d1db4a7d7a4c52dd47eb1788a6e4e476mvstanton@chromium.org  if (Serializer::enabled()) {
2963182d2db4d1db4a7d7a4c52dd47eb1788a6e4e476mvstanton@chromium.org    PlatformFeatureScope sse2(SSE2);
2964ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    BinaryOpICStub::GenerateAheadOfTime(isolate);
2965182d2db4d1db4a7d7a4c52dd47eb1788a6e4e476mvstanton@chromium.org  } else {
2966ce9c514a4e015930324b2b45326a478a69535388machenbach@chromium.org    BinaryOpICStub::GenerateAheadOfTime(isolate);
2967182d2db4d1db4a7d7a4c52dd47eb1788a6e4e476mvstanton@chromium.org  }
2968c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2969c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2970c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
29718432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CodeStub::GenerateFPStubs(Isolate* isolate) {
2972a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (CpuFeatures::IsSupported(SSE2)) {
2973a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CEntryStub save_doubles(1, kSaveFPRegs);
2974a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Stubs might already be in the snapshot, detect that and don't regenerate,
2975a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // which would lead to code stub initialization state being messed up.
2976a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Code* save_doubles_code;
29778432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
29788432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org      save_doubles_code = *(save_doubles.GetCode(isolate));
2979a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
29808432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    isolate->set_fp_stubs_generated(true);
2981a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
2982c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2983c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2984c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
29858432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
2986c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CEntryStub stub(1, kDontSaveFPRegs);
29878a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  stub.GetCode(isolate);
2988c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
2989c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
2990c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
299159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgstatic void JumpIfOOM(MacroAssembler* masm,
299259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                      Register value,
299359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                      Register scratch,
299459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                      Label* oom_label) {
299559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(scratch, value);
299659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3);
299759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  STATIC_ASSERT(kFailureTag == 3);
299859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ and_(scratch, 0xf);
299959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(scratch, 0xf);
300059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ j(equal, oom_label);
300159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org}
300259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
300359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org
300465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CEntryStub::GenerateCore(MacroAssembler* masm,
300565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* throw_normal_exception,
300665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* throw_termination_exception,
300765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* throw_out_of_memory_exception,
300865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              bool do_gc,
30090ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org                              bool always_allocate_scope) {
301065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result parameter for PerformGC, if any
301165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: pointer to C function  (C callee-saved)
301265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebp: frame pointer  (restored after C call)
301365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esp: stack pointer  (restored after C call)
301465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: number of arguments including receiver  (C callee-saved)
301565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esi: pointer to the first argument (C callee-saved)
301665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
301765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result returned in eax, or eax+edx if result_size_ is 2.
301865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
301965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check stack alignment.
302065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (FLAG_debug_code) {
302165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CheckStackAlignment();
302265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
302365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
302465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (do_gc) {
302565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Pass failure code returned from last attempt as first argument to
302665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the
302765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // stack alignment is known to be correct. This function takes one argument
302865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // which is passed on the stack, and we know that the stack has been
302965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // prepared to pass at least one argument.
3030528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    __ mov(Operand(esp, 1 * kPointerSize),
3031528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org           Immediate(ExternalReference::isolate_address(masm->isolate())));
303265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(Operand(esp, 0 * kPointerSize), eax);  // Result.
303365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);
303465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
303565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
303665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ExternalReference scope_depth =
3037ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
303865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (always_allocate_scope) {
303965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ inc(Operand::StaticVariable(scope_depth));
304065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
304165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
304265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call C function.
304365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 0 * kPointerSize), edi);  // argc.
304465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), esi);  // argv.
3045ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ mov(Operand(esp, 2 * kPointerSize),
304632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org         Immediate(ExternalReference::isolate_address(masm->isolate())));
3047c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ call(ebx);
304865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result is in eax or edx:eax - do not destroy these registers!
304965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
305065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (always_allocate_scope) {
305165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ dec(Operand::StaticVariable(scope_depth));
305265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
305365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3054ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Runtime functions should not return 'the hole'.  Allowing it to escape may
3055ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // lead to crashes in the IC code later.
305665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (FLAG_debug_code) {
305783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label okay;
30587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ cmp(eax, masm->isolate()->factory()->the_hole_value());
305983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(not_equal, &okay, Label::kNear);
306065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ int3();
306165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&okay);
306265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
306365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
306465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check for failure result.
306565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label failure_returned;
306665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
306765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(ecx, Operand(eax, 1));
306865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Lower 2 bits of ecx are 0 iff eax has failure tag.
306965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ test(ecx, Immediate(kFailureTagMask));
30707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(zero, &failure_returned);
307165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3072ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ExternalReference pending_exception_address(
307383e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org      Isolate::kPendingExceptionAddress, masm->isolate());
3074d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
3075d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // Check that there is no pending exception, otherwise we
3076d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // should have returned some failure value.
3077d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  if (FLAG_debug_code) {
3078d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ push(edx);
3079c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
308083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label okay;
3081d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ cmp(edx, Operand::StaticVariable(pending_exception_address));
3082d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    // Cannot use check here as it attempts to generate call into runtime.
308383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(equal, &okay, Label::kNear);
3084d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ int3();
3085d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ bind(&okay);
3086d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ pop(edx);
3087d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
3088d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
308965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Exit the JavaScript to C++ exit frame.
3090c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ LeaveExitFrame(save_doubles_ == kSaveFPRegs);
309165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
309265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
309365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handling of failure.
309465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&failure_returned);
309565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
309665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label retry;
309765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the returned exception is RETRY_AFTER_GC continue at retry label
309865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
309965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
31004668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(zero, &retry, Label::kNear);
310165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
310265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Special handling of out of memory exceptions.
310359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  JumpIfOOM(masm, eax, ecx, throw_out_of_memory_exception);
310465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3105e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Retrieve the pending exception.
310665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand::StaticVariable(pending_exception_address));
3107e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
3108e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // See if we just retrieved an OOM exception.
3109e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  JumpIfOOM(masm, eax, ecx, throw_out_of_memory_exception);
3110e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
3111e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Clear the pending exception.
3112c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
311365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand::StaticVariable(pending_exception_address), edx);
311465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
311565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Special handling of termination exceptions which are uncatchable
311665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // by javascript code.
31177979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(eax, masm->isolate()->factory()->termination_exception());
311865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(equal, throw_termination_exception);
311965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
312065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle normal exception.
312165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(throw_normal_exception);
312265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
312365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Retry.
312465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&retry);
312565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
312665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
312765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
312865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CEntryStub::Generate(MacroAssembler* masm) {
312965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: number of arguments including receiver
313065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: pointer to C function  (C callee-saved)
313165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebp: frame pointer  (restored after C call)
313265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esp: stack pointer  (restored after C call)
313365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esi: current context (C callee-saved)
313465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: JS function of the caller (C callee-saved)
313565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
31361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm);
31371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
313865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // NOTE: Invocations of builtins may return failure objects instead
313965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // of a proper result. The builtin entry handles this by performing
314065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // a garbage collection and retrying the builtin (twice).
314165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
314265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Enter the exit frame that transitions from JavaScript to C++.
3143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ EnterExitFrame(save_doubles_ == kSaveFPRegs);
314465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
314565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result parameter for PerformGC, if any (setup below)
314665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: pointer to builtin function  (C callee-saved)
314765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebp: frame pointer  (restored after C call)
314865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esp: stack pointer  (restored after C call)
314965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: number of arguments including receiver (C callee-saved)
315065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esi: argv pointer (C callee-saved)
315165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
315265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label throw_normal_exception;
315365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label throw_termination_exception;
315465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label throw_out_of_memory_exception;
315565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
315665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call into the runtime system.
315765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCore(masm,
315865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_normal_exception,
315965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_termination_exception,
316065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_out_of_memory_exception,
316165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               false,
316265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               false);
316365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
316465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do space-specific GC and retry runtime call.
316565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCore(masm,
316665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_normal_exception,
316765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_termination_exception,
316865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_out_of_memory_exception,
316965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               true,
317065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               false);
317165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
317265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Do full GC and retry runtime call one final time.
317365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Failure* failure = Failure::InternalError();
317465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
317565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCore(masm,
317665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_normal_exception,
317765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_termination_exception,
317865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               &throw_out_of_memory_exception,
317965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               true,
318065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org               true);
318165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
318265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&throw_out_of_memory_exception);
318365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Set external caught exception to false.
318465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  Isolate* isolate = masm->isolate();
318565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
318665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                                    isolate);
318765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(Operand::StaticVariable(external_caught), Immediate(false));
318865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org
318965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Set pending exception and eax to out of memory exception.
319065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
319165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org                                      isolate);
319259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  Label already_have_failure;
319359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  JumpIfOOM(masm, eax, ecx, &already_have_failure);
319459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException(0x1)));
319559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ bind(&already_have_failure);
319665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ mov(Operand::StaticVariable(pending_exception), eax);
319765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  // Fall through to the next label.
319865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
319965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&throw_termination_exception);
320065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ ThrowUncatchable(eax);
320165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
320265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&throw_normal_exception);
320365a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org  __ Throw(eax);
320465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
320565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
320665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
320765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
320804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  Label invoke, handler_entry, exit;
320965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label not_outermost_js, not_outermost_js_2;
321065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
32111510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm);
32121510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
3213f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up frame.
321465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(ebp);
3215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(ebp, esp);
321665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
321765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Push marker in two places.
321865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
321965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(Immediate(Smi::FromInt(marker)));  // context slot
322065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(Immediate(Smi::FromInt(marker)));  // function slot
322165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Save callee-saved registers (C calling conventions).
322265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(edi);
322365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(esi);
322465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(ebx);
322565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
322665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Save copies of the top frame descriptor on the stack.
322783e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, masm->isolate());
322865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(Operand::StaticVariable(c_entry_fp));
322965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
323065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If this is the outermost JS call, set js_entry_sp value.
323183e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress,
3232ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                masm->isolate());
323365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
32344668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(not_equal, &not_outermost_js, Label::kNear);
323565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand::StaticVariable(js_entry_sp), ebp);
3236c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
32372c26cb18967944507a81a07ac6f1c921ebb4ab75danno@chromium.org  __ jmp(&invoke, Label::kNear);
323865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_outermost_js);
3239c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
324065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
324104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Jump to a faked try block that does the invoke, with a faked catch
324204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // block that sets the pending exception.
324304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ jmp(&invoke);
324404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&handler_entry);
324504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  handler_offset_ = handler_entry.pos();
324604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Caught exception: Store result (exception) in the pending exception
324704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // field in the JSEnv and return a failure sentinel.
324883e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org  ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
3249ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                                      masm->isolate());
325065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand::StaticVariable(pending_exception), eax);
325165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
325265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&exit);
325365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
325404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Invoke: Link this frame into the handler chain.  There's only one
325504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // handler block in this code object, so its index is 0.
325665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&invoke);
325778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org  __ PushTryHandler(StackHandler::JS_ENTRY, 0);
325865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
325965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Clear any pending exceptions.
3260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value()));
326165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand::StaticVariable(pending_exception), edx);
326265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
326365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fake a receiver (NULL).
326465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(Immediate(0));  // receiver
326565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
326604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Invoke the function by calling through JS entry trampoline builtin and
326704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // pop the faked function when we return. Notice that we cannot store a
326804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // reference to the trampoline code directly in this stub, because the
326904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // builtin stubs may not have been generated yet.
327065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (is_construct) {
327104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
327204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                      masm->isolate());
327365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(edx, Immediate(construct_entry));
327465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
32757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    ExternalReference entry(Builtins::kJSEntryTrampoline,
3276ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                            masm->isolate());
327765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(edx, Immediate(entry));
327865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
327965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, Operand(edx, 0));  // deref address
328065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
3281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ call(edx);
328265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
328365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Unlink this frame from the handler chain.
3284c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ PopTryHandler();
328565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3286c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&exit);
3287c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check if the current stack frame is marked as the outermost JS frame.
3288c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ pop(ebx);
3289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
329065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, &not_outermost_js_2);
329165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
329265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_outermost_js_2);
329365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
329465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Restore the top frame descriptor from the stack.
3295ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ pop(Operand::StaticVariable(ExternalReference(
329683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org      Isolate::kCEntryFPAddress,
3297ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      masm->isolate())));
329865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
329965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Restore callee-saved registers (C calling conventions).
330065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(ebx);
330165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(esi);
330265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(edi);
3303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(esp, Immediate(2 * kPointerSize));  // remove markers
330465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
330565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Restore frame pointer and return.
330665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(ebp);
330765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
330865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
330965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
331065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3311d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// Generate stub code for instanceof.
3312d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// This code can patch a call site inlined cache of the instance of check,
3313d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// which looks like this.
3314d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//
3315d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//   81 ff XX XX XX XX   cmp    edi, <the hole, patched to a map>
3316d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//   75 0a               jne    <some near label>
3317d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//   b8 XX XX XX XX      mov    eax, <the hole, patched to either true or false>
3318d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//
3319d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// If call site patching is requested the stack will have the delta from the
3320d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// return address to the cmp instruction just below the return address. This
3321d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// also means that call site patching can only take place with arguments in
3322d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org// registers. TOS looks like this when call site patching is requested
3323d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//
3324d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//   esp[0] : return address
3325d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//   esp[4] : delta from return address to cmp instruction
3326d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org//
332765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid InstanceofStub::Generate(MacroAssembler* masm) {
3328d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // Call site inlining and patching implies arguments in registers.
3329d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
3330d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
33315f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Fixed register usage throughout the stub.
33325f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Register object = eax;  // Object (lhs).
33335f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Register map = ebx;  // Map of the object.
33345f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Register function = edx;  // Function (rhs).
33355f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Register prototype = edi;  // Prototype of the function.
33365f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Register scratch = ecx;
33375f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
3338d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // Constants describing the call site code to patch.
3339d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  static const int kDeltaToCmpImmediate = 2;
3340d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  static const int kDeltaToMov = 8;
3341d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  static const int kDeltaToMovImmediate = 9;
3342f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  static const int8_t kCmpEdiOperandByte1 = BitCast<int8_t, uint8_t>(0x3b);
3343f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d);
3344d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8);
3345d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
3346d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  ASSERT_EQ(object.code(), InstanceofStub::left().code());
3347d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  ASSERT_EQ(function.code(), InstanceofStub::right().code());
3348d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
33495f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Get the object and function - they are always both needed.
33505f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Label slow, not_js_object;
3351d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!HasArgsInRegisters()) {
33525f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    __ mov(object, Operand(esp, 2 * kPointerSize));
33535f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    __ mov(function, Operand(esp, 1 * kPointerSize));
33545f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
335565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
335665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the left hand is a JS object.
33577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(object, &not_js_object);
33585f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
335965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3360d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // If there is a call site cache don't look in the global cache, but do the
3361d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // real lookup and update the call site cache.
3362d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!HasCallSiteInlineCheck()) {
3363d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Look up the function and the map in the instanceof cache.
336483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label miss;
3365594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
336683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(not_equal, &miss, Label::kNear);
3367594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex);
336883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(not_equal, &miss, Label::kNear);
3369594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex);
3370d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
3371d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ bind(&miss);
3372d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  }
3373d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
33745f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Get the prototype of the function.
3375394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
337665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
337765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check that the function prototype is a JS object.
33787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(prototype, &slow);
33795f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
33805f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
3381d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // Update the global instanceof or call site inlined cache with the current
3382d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // map and function. The cached answer will be set when it is known below.
3383d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!HasCallSiteInlineCheck()) {
3384594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ StoreRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex);
3385594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
3386d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  } else {
3387d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // The constants for the code patching are based on no push instructions
3388d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // at the call site.
3389d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    ASSERT(HasArgsInRegisters());
3390d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Get return address and delta to inlined map check.
3391d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ mov(scratch, Operand(esp, 0 * kPointerSize));
3392d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ sub(scratch, Operand(esp, 1 * kPointerSize));
3393d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (FLAG_debug_code) {
3394f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1);
3395594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp1);
3396f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2);
3397594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCmp2);
3398d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
3399f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate));
3400f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    __ mov(Operand(scratch, 0), map);
3401d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  }
34025f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
34035f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Loop through the prototype chain of the object looking for the function
34045f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // prototype.
34055f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset));
340683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label loop, is_instance, is_not_instance;
340765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
3408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(scratch, prototype);
340983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(equal, &is_instance, Label::kNear);
34107979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
3411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(scratch, Immediate(factory->null_value()));
341283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(equal, &is_not_instance, Label::kNear);
34135f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
34145f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
341565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&loop);
341665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
341765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&is_instance);
3418d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!HasCallSiteInlineCheck()) {
3419594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ mov(eax, Immediate(0));
3420594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
3421d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  } else {
3422d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Get return address and delta to inlined map check.
34237979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ mov(eax, factory->true_value());
3424d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ mov(scratch, Operand(esp, 0 * kPointerSize));
3425d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ sub(scratch, Operand(esp, 1 * kPointerSize));
3426d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (FLAG_debug_code) {
3427d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
3428594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
3429d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
3430d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
3431d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (!ReturnTrueFalseObject()) {
3432d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ Set(eax, Immediate(0));
3433d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
3434d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  }
3435d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
343665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
343765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&is_not_instance);
3438d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!HasCallSiteInlineCheck()) {
3439594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ mov(eax, Immediate(Smi::FromInt(1)));
3440594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
3441d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  } else {
3442d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Get return address and delta to inlined map check.
34437979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ mov(eax, factory->false_value());
3444d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ mov(scratch, Operand(esp, 0 * kPointerSize));
3445d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ sub(scratch, Operand(esp, 1 * kPointerSize));
3446d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (FLAG_debug_code) {
3447d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
3448594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
3449d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
3450d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ mov(Operand(scratch, kDeltaToMovImmediate), eax);
3451d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (!ReturnTrueFalseObject()) {
3452d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ Set(eax, Immediate(Smi::FromInt(1)));
3453d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
3454d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  }
3455d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
34565f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
34575f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Label object_not_null, object_not_null_or_smi;
34585f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ bind(&not_js_object);
34595f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Before null, smi and string value checks, check that the rhs is a function
34605f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // as for a non-function rhs an exception needs to be thrown.
34614668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ JumpIfSmi(function, &slow, Label::kNear);
34625f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
34634668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(not_equal, &slow, Label::kNear);
34645f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
34655f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Null is not instance of anything.
34667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(object, factory->null_value());
34674668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(not_equal, &object_not_null, Label::kNear);
34685f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ Set(eax, Immediate(Smi::FromInt(1)));
3469d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
34705f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
34715f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ bind(&object_not_null);
34725f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Smi values is not instance of anything.
34734668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear);
34745f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ Set(eax, Immediate(Smi::FromInt(1)));
3475d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
34765f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
34775f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ bind(&object_not_null_or_smi);
34785f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // String values is not instance of anything.
34795f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  Condition is_string = masm->IsObjectStringType(object, scratch, scratch);
34804668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  __ j(NegateCondition(is_string), &slow, Label::kNear);
34815f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  __ Set(eax, Immediate(Smi::FromInt(1)));
3482d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
348365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
348465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Slow-case: Go through the JavaScript implementation.
348565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow);
3486d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!ReturnTrueFalseObject()) {
3487d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Tail call the builtin which returns 0 or 1.
3488d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (HasArgsInRegisters()) {
3489d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // Push arguments below return address.
3490d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ pop(scratch);
3491d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ push(object);
3492d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ push(function);
3493d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ push(scratch);
3494d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
3495d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
3496d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  } else {
3497d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Call the builtin and convert 0/1 to true/false.
3498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
3499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      FrameScope scope(masm, StackFrame::INTERNAL);
3500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(object);
3501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ push(function);
3502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
3503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
350483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label true_value, done;
3505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ test(eax, eax);
350683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(zero, &true_value, Label::kNear);
35077979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ mov(eax, factory->false_value());
350883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ jmp(&done, Label::kNear);
3509d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ bind(&true_value);
35107979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ mov(eax, factory->true_value());
3511d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ bind(&done);
3512d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
35135f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
351465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
351565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
351665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3517d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.orgRegister InstanceofStub::left() { return eax; }
3518d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
3519d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
3520d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.orgRegister InstanceofStub::right() { return edx; }
3521d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
3522d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
352365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// -------------------------------------------------------------------------
352465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// StringCharCodeAtGenerator
352565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
352665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
352765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the receiver is a smi trigger the non-string case.
352865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
35297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(object_, receiver_not_string_);
353065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
353165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fetch the instance type of the receiver into result register.
353265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
353365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
353465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the receiver is not a string trigger the non-string case.
353565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ test(result_, Immediate(kIsNotStringMask));
353665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_zero, receiver_not_string_);
353765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
353865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If the index is non-smi trigger the non-smi case.
353965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
35407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(index_, &index_not_smi_);
354165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&got_smi_index_);
354265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
354365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check for index out of range.
3544c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ cmp(index_, FieldOperand(object_, String::kLengthOffset));
354565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(above_equal, index_out_of_range_);
354665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
35470ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ SmiUntag(index_);
354865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
35490ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  Factory* factory = masm->isolate()->factory();
35500ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  StringCharLoadGenerator::Generate(
35510ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry      masm, factory, object_, index_, result_, &call_runtime_);
355265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
355365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiTag(result_);
355465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&exit_);
355565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
355665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
355765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
355865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharCodeAtGenerator::GenerateSlow(
3559c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
3560c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    const RuntimeCallHelper& call_helper) {
3561594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
356265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
356365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Index is not a smi.
356465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&index_not_smi_);
356565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If index is a heap number, try converting it to an integer.
35667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ CheckMap(index_,
35677979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org              masm->isolate()->factory()->heap_number_map(),
35687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org              index_not_number_,
3569c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org              DONT_DO_SMI_CHECK);
357065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.BeforeCall(masm);
357165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(object_);
357265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(index_);  // Consumed by runtime conversion function.
357365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
357465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
357565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
357665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
357765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // NumberToSmi discards numbers that are not exact integers.
357865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CallRuntime(Runtime::kNumberToSmi, 1);
357965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
3580c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  if (!index_.is(eax)) {
358165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Save the conversion result before the pop instructions below
358265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // have a chance to overwrite it.
3583c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    __ mov(index_, eax);
358465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
358565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(object_);
358665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Reload the instance type.
358765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
358865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
358965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.AfterCall(masm);
359065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If index is still not a smi, it must be out of range.
359165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
3592c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ JumpIfNotSmi(index_, index_out_of_range_);
359365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Otherwise, return to the fast path.
359465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&got_smi_index_);
359565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
359665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call runtime. We get here when the receiver is a string and the
359765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // index is a number, but the code of getting the actual character
359865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // is too complex (e.g., when the string needs to be flattened).
359965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&call_runtime_);
360065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.BeforeCall(masm);
360165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(object_);
36020ad885c06ff6a0d68bc9ad75629f7ddfaa6860b9erikcorry  __ SmiTag(index_);
360365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(index_);
360465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CallRuntime(Runtime::kStringCharCodeAt, 2);
360565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!result_.is(eax)) {
360665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(result_, eax);
360765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
360865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.AfterCall(masm);
360965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&exit_);
361065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3611594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
361265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
361365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
361465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
361565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// -------------------------------------------------------------------------
361665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// StringCharFromCodeGenerator
361765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
361865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
361965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fast case of Heap::LookupSingleCharacterStringFromCode.
362065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
362165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiShiftSize == 0);
362259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1));
362365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ test(code_,
362465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org          Immediate(kSmiTagMask |
362559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                    ((~String::kMaxOneByteCharCode) << kSmiTagSize)));
36267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(not_zero, &slow_case_);
362765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
36287979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Factory* factory = masm->isolate()->factory();
36297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Set(result_, Immediate(factory->single_character_string_cache()));
363065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
363165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
363265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiShiftSize == 0);
36332efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // At this point code register contains smi tagged ASCII char code.
363465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(result_, FieldOperand(result_,
363565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               code_, times_half_pointer_size,
363665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               FixedArray::kHeaderSize));
36377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmp(result_, factory->undefined_value());
36387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(equal, &slow_case_);
363965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&exit_);
364065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
364165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
364265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
364365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharFromCodeGenerator::GenerateSlow(
3644c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    MacroAssembler* masm,
3645c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    const RuntimeCallHelper& call_helper) {
3646594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
364765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
364865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&slow_case_);
364965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.BeforeCall(masm);
365065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(code_);
365165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ CallRuntime(Runtime::kCharFromCode, 1);
365265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!result_.is(eax)) {
365365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(result_, eax);
365465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
365565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  call_helper.AfterCall(masm);
365665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&exit_);
365765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
3658594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
365965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
366065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
366165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
366265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringAddStub::Generate(MacroAssembler* masm) {
36637ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label call_runtime, call_builtin;
36643cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  Builtins::JavaScript builtin_id = Builtins::ADD;
366565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
366665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load the two arguments.
366765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, 2 * kPointerSize));  // First argument.
366865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, Operand(esp, 1 * kPointerSize));  // Second argument.
366965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
367065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make sure that both arguments are strings if not known in advance.
3671ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Otherwise, at least one of the arguments is definitely a string,
3672ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // and we convert the one that is not known to be a string.
3673ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) {
3674ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT);
3675ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT);
36767ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ JumpIfSmi(eax, &call_runtime);
367765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
36787ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ j(above_equal, &call_runtime);
367965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
368065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // First argument is a a string, test second.
36817ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ JumpIfSmi(edx, &call_runtime);
368265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
36837ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    __ j(above_equal, &call_runtime);
3684ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
3685ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0);
3686ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi,
3687ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                            &call_builtin);
3688ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    builtin_id = Builtins::STRING_ADD_RIGHT;
3689ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
3690ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0);
3691ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi,
3692ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org                            &call_builtin);
3693ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    builtin_id = Builtins::STRING_ADD_LEFT;
369465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
369565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
369665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Both arguments are strings.
369765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: first string
369865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: second string
369965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if either of the strings are empty. In that case return the other.
370083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label second_not_zero_length, both_not_zero_length;
370165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
370265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
3703c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ecx, ecx);
370483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_zero, &second_not_zero_length, Label::kNear);
370565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Second string is empty, result is first string which is already in eax.
37067979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
37077979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
370865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
370965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&second_not_zero_length);
371065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
371165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
3712c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ebx, ebx);
371383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_zero, &both_not_zero_length, Label::kNear);
371465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // First string is empty, result is second string which is in edx.
371565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, edx);
37167979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
371765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
371865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
371965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Both strings are non-empty.
372065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: first string
372165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: length of first string as a smi
372265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: length of second string as a smi
372365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: second string
372465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Look at the length of the result of adding the two strings.
372565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label string_add_flat_result, longer_than_two;
372665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&both_not_zero_length);
3727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, ecx);
372865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
372965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle exceptionally long strings in the runtime system.
37307ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ j(overflow, &call_runtime);
37314a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Use the string table when adding two one character strings, as it
37324a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // helps later optimizations to return an internalized string here.
3733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, Immediate(Smi::FromInt(2)));
373465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_equal, &longer_than_two);
373565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
37362efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Check that both strings are non-external ASCII strings.
37377ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime);
373865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
37393cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Get the two characters forming the new string.
3740fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
3741fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
374265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
37434a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Try to lookup two character string in string table. If it is not found
374465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // just allocate a new one.
37453cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  Label make_two_character_string, make_two_character_string_no_reload;
37464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  StringHelper::GenerateTwoCharacterStringTableProbe(
37473cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org      masm, ebx, ecx, eax, edx, edi,
37483cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org      &make_two_character_string_no_reload, &make_two_character_string);
37497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
375065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
375165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
37523cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Allocate a two character string.
375365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&make_two_character_string);
37543cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Reload the arguments.
37553cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ mov(eax, Operand(esp, 2 * kPointerSize));  // First argument.
37563cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ mov(edx, Operand(esp, 1 * kPointerSize));  // Second argument.
37573cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Get the two characters forming the new string.
3758fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ movzx_b(ebx, FieldOperand(eax, SeqOneByteString::kHeaderSize));
3759fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ movzx_b(ecx, FieldOperand(edx, SeqOneByteString::kHeaderSize));
37603cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ bind(&make_two_character_string_no_reload);
37617979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_make_two_char(), 1);
37627ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime);
37633cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Pack both characters in ebx.
37643cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ shl(ecx, kBitsPerByte);
3765c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ or_(ebx, ecx);
37663cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Set the characters in the new string.
3767fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ mov_w(FieldOperand(eax, SeqOneByteString::kHeaderSize), ebx);
37687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
37693cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ ret(2 * kPointerSize);
377065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
377165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&longer_than_two);
377265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if resulting string will be flat.
37732efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength)));
377465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(below, &string_add_flat_result);
377565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
377665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If result is not supposed to be flat allocate a cons string object. If both
37772efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // strings are ASCII the result is an ASCII cons string.
377865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label non_ascii, allocated, ascii_data;
377965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
378065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
378165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
378265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
3783c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ and_(ecx, edi);
3784e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
37851805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
37861805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ test(ecx, Immediate(kStringEncodingMask));
378765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(zero, &non_ascii);
378865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&ascii_data);
37892efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Allocate an ASCII cons string.
37907ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime);
379165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&allocated);
379265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Fill the fields of the cons string.
3793c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  __ AssertSmi(ebx);
379465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
379565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
379665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Immediate(String::kEmptyHashField));
379757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
379857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Label skip_write_barrier, after_writing;
379957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  ExternalReference high_promotion_mode = ExternalReference::
380057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org      new_space_high_promotion_mode_active_address(masm->isolate());
380157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ test(Operand::StaticVariable(high_promotion_mode), Immediate(1));
380257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ j(zero, &skip_write_barrier);
380357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
380465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
380557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ RecordWriteField(ecx,
380657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     ConsString::kFirstOffset,
380757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     eax,
380857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     ebx,
380957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     kDontSaveFPRegs);
381065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
381157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ RecordWriteField(ecx,
381257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     ConsString::kSecondOffset,
381357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     edx,
381457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     ebx,
381557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                     kDontSaveFPRegs);
381657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ jmp(&after_writing);
381757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
381857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ bind(&skip_write_barrier);
381957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
382057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
382157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
382257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ bind(&after_writing);
382357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
382465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, ecx);
38257979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
382665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
382765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&non_ascii);
382865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // At least one of the strings is two-byte. Check whether it happens
3829ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // to contain only one byte characters.
383065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: first instance type AND second instance type.
383165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: second instance type.
3832ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ test(ecx, Immediate(kOneByteDataHintMask));
383365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_zero, &ascii_data);
383446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
383546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
383646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ xor_(edi, ecx);
3837ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0);
3838ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ and_(edi, kOneByteStringTag | kOneByteDataHintTag);
3839ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ cmp(edi, kOneByteStringTag | kOneByteDataHintTag);
384046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ j(equal, &ascii_data);
384165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Allocate a two byte cons string.
38427ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateTwoByteConsString(ecx, edi, no_reg, &call_runtime);
384365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(&allocated);
384465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
38457ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // We cannot encounter sliced strings or cons strings here since:
38462efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
38477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Handle creating a flat result from either external or sequential strings.
38487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Locate the first characters' locations.
384965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: first string
385065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: length of resulting flat string as a smi
385165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: second string
38527ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label first_prepared, second_prepared;
38537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label first_is_sequential, second_is_sequential;
385465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&string_add_flat_result);
385565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
385665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
38577ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // ecx: instance type of first string
38587ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
38597ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ test_b(ecx, kStringRepresentationMask);
38607ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ j(zero, &first_is_sequential, Label::kNear);
38617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Rule out short external string and load string resource.
38627ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kShortExternalStringTag != 0);
38637ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ test_b(ecx, kShortExternalStringMask);
38647ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ j(not_zero, &call_runtime);
38657ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
3866fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
38677ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ jmp(&first_prepared, Label::kNear);
38687ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&first_is_sequential);
3869fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(eax, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
38707ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&first_prepared);
38717ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
38727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
38737ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
38747ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Check whether both strings have same encoding.
38757ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // edi: instance type of second string
38767ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ xor_(ecx, edi);
38777ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ test_b(ecx, kStringEncodingMask);
38787ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ j(not_zero, &call_runtime);
38797ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
38807ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ test_b(edi, kStringRepresentationMask);
38817ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ j(zero, &second_is_sequential, Label::kNear);
38827ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Rule out short external string and load string resource.
38837ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kShortExternalStringTag != 0);
38847ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ test_b(edi, kShortExternalStringMask);
38857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ j(not_zero, &call_runtime);
38867ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset));
3887fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
38887ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ jmp(&second_prepared, Label::kNear);
38897ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&second_is_sequential);
3890fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(edx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
38917ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&second_prepared);
38927ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
38937ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Push the addresses of both strings' first characters onto the stack.
38947ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ push(edx);
38957ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ push(eax);
38967ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org
38977ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  Label non_ascii_string_add_flat_result, call_runtime_drop_two;
38987ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // edi: instance type of second string
38997ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // First string and second string have the same encoding.
39007ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  STATIC_ASSERT(kTwoByteStringTag == 0);
39017ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ test_b(edi, kStringEncodingMask);
390265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(zero, &non_ascii_string_add_flat_result);
390365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
39042efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Both strings are ASCII strings.
390565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: length of resulting flat string as a smi
390665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(ebx);
39077ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
390865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
390965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, eax);
391065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate first character of result.
3911fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(ecx, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
39127ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Load first argument's length and first character location.  Account for
39137ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // values currently on the stack when fetching arguments from it.
39147ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(edx, Operand(esp, 4 * kPointerSize));
391565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
391665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(edi);
39177ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ pop(edx);
391865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
391965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: first character of result
392065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: first char of first argument
392165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: length of first argument
392265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
39237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Load second argument's length and first character location.  Account for
39247ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // values currently on the stack when fetching arguments from it.
39257ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(edx, Operand(esp, 2 * kPointerSize));
392665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
392765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(edi);
39287ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ pop(edx);
392965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
393065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: next character of result
393165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: first char of second argument
393265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: length of second argument
393365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
39347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
393565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
393665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
393765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Handle creating a flat two byte result.
393865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: first string - known to be two byte
393965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: length of resulting flat string as a smi
394065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: second string
394165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&non_ascii_string_add_flat_result);
39427ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Both strings are two byte strings.
394365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(ebx);
39447ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
394565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
394665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, eax);
394765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate first character of result.
39487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ add(ecx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
39497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Load second argument's length and first character location.  Account for
39507ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // values currently on the stack when fetching arguments from it.
39517ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(edx, Operand(esp, 4 * kPointerSize));
395265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
395365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(edi);
39547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ pop(edx);
395565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
395665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: first character of result
395765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: first char of first argument
395865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: length of first argument
395965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
39607ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Load second argument's length and first character location.  Account for
39617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // values currently on the stack when fetching arguments from it.
39627ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ mov(edx, Operand(esp, 2 * kPointerSize));
396365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
396465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(edi);
39657ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ pop(edx);
396665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
396765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: next character of result
396865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: first char of second argument
396965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: length of second argument
397065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
39717979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_add_native(), 1);
397265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
397365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
39747ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // Recover stack pointer before jumping to runtime.
39757ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&call_runtime_drop_two);
39767ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ Drop(2);
397765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Just jump to runtime to add the two strings.
39787ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  __ bind(&call_runtime);
3979e94b5ff1e1e95fb2c8ef6bce66ce8533786d9792bmeurer@chromium.org  __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
39803cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org
39813cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  if (call_builtin.is_linked()) {
39823cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org    __ bind(&call_builtin);
3983e94b5ff1e1e95fb2c8ef6bce66ce8533786d9792bmeurer@chromium.org    __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
39843cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  }
39853cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org}
39863cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org
39873cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org
39884e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgvoid StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
39894e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ push(eax);
39904e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ push(edx);
39914e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
39924e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
39934e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
39944e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgvoid StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
39954e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org                                            Register temp) {
39964e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ pop(temp);
39974e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ pop(edx);
39984e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ pop(eax);
39994e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  __ push(temp);
40004e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
40014e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
40024e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
40033cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.orgvoid StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
40043cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                            int stack_offset,
40053cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                            Register arg,
40063cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                            Register scratch1,
40073cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                            Register scratch2,
40083cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                            Register scratch3,
40093cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                            Label* slow) {
40103cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // First check if the argument is already a string.
40113cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  Label not_string, done;
40127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(arg, &not_string);
40133cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
40143cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ j(below, &done);
40153cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org
40163cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Check the number to string cache.
40173cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ bind(&not_string);
40183cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  // Puts the cached result into scratch1.
4019528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
40203cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ mov(arg, scratch1);
40213cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ mov(Operand(esp, stack_offset), arg);
40223cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ bind(&done);
402365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
402465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
402565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
402665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
402765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register dest,
402865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register src,
402965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register count,
403065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          Register scratch,
403165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                          bool ascii) {
403283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label loop;
403365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
403465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // This loop just copies one character at a time, as it is only used for very
403565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // short strings.
403665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (ascii) {
403765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov_b(scratch, Operand(src, 0));
403865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov_b(Operand(dest, 0), scratch);
4039c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(src, Immediate(1));
4040c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(dest, Immediate(1));
404165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
404265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov_w(scratch, Operand(src, 0));
404365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov_w(Operand(dest, 0), scratch);
4044c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(src, Immediate(2));
4045c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(dest, Immediate(2));
404665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
4047c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(count, Immediate(1));
404865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_zero, &loop);
404965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
405065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
405165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
405265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
405365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             Register dest,
405465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             Register src,
405565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             Register count,
405665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             Register scratch,
405765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                             bool ascii) {
405865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy characters using rep movs of doublewords.
405965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The destination is aligned on a 4 byte boundary because we are
406065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // copying to the beginning of a newly allocated string.
406165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(dest.is(edi));  // rep movs destination
406265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(src.is(esi));  // rep movs source
406365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(count.is(ecx));  // rep movs count
406465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(!scratch.is(dest));
406565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(!scratch.is(src));
406665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  ASSERT(!scratch.is(count));
406765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
406865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Nothing to do for zero characters.
406965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label done;
4070c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(count, count);
407165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(zero, &done);
407265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
407365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make count the number of bytes to copy.
407465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!ascii) {
407565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ shl(count, 1);
407665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
407765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
407865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Don't enter the rep movs if there are less than 4 bytes to copy.
407983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label last_bytes;
408065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ test(count, Immediate(~3));
408183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(zero, &last_bytes, Label::kNear);
408265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
408365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy from edi to esi using rep movs instruction.
408465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, count);
408565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sar(count, 2);  // Number of doublewords to copy.
408665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cld();
408765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ rep_movs();
408865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
408965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Find number of bytes left.
409065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(count, scratch);
409165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ and_(count, 3);
409265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
409365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Check if there are more bytes to copy.
409465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&last_bytes);
4095c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(count, count);
409665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(zero, &done);
409765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
409865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Copy remaining characters.
409983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label loop;
410065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&loop);
410165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov_b(scratch, Operand(src, 0));
410265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov_b(Operand(dest, 0), scratch);
4103c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(src, Immediate(1));
4104c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(dest, Immediate(1));
4105c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(count, Immediate(1));
410665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(not_zero, &loop);
410765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
410865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&done);
410965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
411065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
411165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
411365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register c1,
411465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register c2,
411565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch1,
411665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch2,
411765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch3,
41183cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org                                                        Label* not_probed,
411965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Label* not_found) {
412065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Register scratch3 is the general scratch register in this function.
412165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register scratch = scratch3;
412265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
412365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make sure that both characters are not digits as such strings has a
41244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // different hash algorithm. Don't try to look for these in the string table.
412583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label not_array_index;
412665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, c1);
4127c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(scratch, Immediate(static_cast<int>('0')));
4128c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(scratch, Immediate(static_cast<int>('9' - '0')));
412983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(above, &not_array_index, Label::kNear);
413065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, c2);
4131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(scratch, Immediate(static_cast<int>('0')));
4132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(scratch, Immediate(static_cast<int>('9' - '0')));
41333cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  __ j(below_equal, not_probed);
413465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
413565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_array_index);
413665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate the two character string hash.
413765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register hash = scratch1;
413865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateHashInit(masm, hash, c1, scratch);
413965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateHashAddCharacter(masm, hash, c2, scratch);
414065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateHashGetHash(masm, hash, scratch);
414165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
414265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Collect the two characters in a register.
414365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register chars = c1;
414465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ shl(c2, kBitsPerByte);
4145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ or_(chars, c2);
414665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
414765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
414865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash:  hash of two character string.
414965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Load the string table.
41514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register string_table = c2;
4152594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ LoadRoot(string_table, Heap::kStringTableRootIndex);
415365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Calculate capacity mask from the string table capacity.
415565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register mask = scratch2;
41564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(mask, FieldOperand(string_table, StringTable::kCapacityOffset));
415765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(mask);
4158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(mask, Immediate(1));
415965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
416065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Registers
416165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // chars:        two character string, char 1 in byte 0 and char 2 in byte 1.
416265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash:         hash of two character string
41634a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // string_table: string table
416465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // mask:         capacity mask
416565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // scratch:      -
416665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41674a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Perform a number of probes in the string table.
416865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  static const int kProbes = 4;
41694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label found_in_string_table;
417065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label next_probe[kProbes], next_probe_pop_mask[kProbes];
41712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  Register candidate = scratch;  // Scratch register contains candidate.
417265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  for (int i = 0; i < kProbes; i++) {
41734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Calculate entry in string table.
417465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(scratch, hash);
417565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (i > 0) {
41764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      __ add(scratch, Immediate(StringTable::GetProbeOffset(i)));
417765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
4178c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ and_(scratch, mask);
417965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
41804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    // Load the entry from the string table.
41814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    STATIC_ASSERT(StringTable::kEntrySize == 1);
418265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(candidate,
41834a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org           FieldOperand(string_table,
418465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                        scratch,
418565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                        times_pointer_size,
41864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org                        StringTable::kElementsStartOffset));
418765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
418865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If entry is undefined no string with this hash can be found.
41897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    Factory* factory = masm->isolate()->factory();
41907979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    __ cmp(candidate, factory->undefined_value());
419165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(equal, not_found);
41922c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org    __ cmp(candidate, factory->the_hole_value());
4193badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    __ j(equal, &next_probe[i]);
419465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
419565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // If length is not 2 the string is not a candidate.
419665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ cmp(FieldOperand(candidate, String::kLengthOffset),
419765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org           Immediate(Smi::FromInt(2)));
419865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(not_equal, &next_probe[i]);
419965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
420065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // As we are out of registers save the mask on the stack and use that
420165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // register as a temporary.
420265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ push(mask);
420365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Register temp = mask;
420465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
42052efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    // Check that the candidate is a non-external ASCII string.
420665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
420765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
420865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ JumpIfInstanceTypeIsNotSequentialAscii(
420965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        temp, temp, &next_probe_pop_mask[i]);
421065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
421165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check if the two characters match.
4212fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize));
421365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ and_(temp, 0x0000ffff);
4214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(chars, temp);
42154a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org    __ j(equal, &found_in_string_table);
421665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&next_probe_pop_mask[i]);
421765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ pop(mask);
421865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ bind(&next_probe[i]);
421965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
422065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
422165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // No matching 2 character string found by probing.
422265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ jmp(not_found);
422365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
422465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Scratch register contains result when we fall through to here.
42252c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  Register result = candidate;
42264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&found_in_string_table);
422765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(mask);  // Pop saved mask from the stack.
422865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (!result.is(eax)) {
422965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ mov(eax, result);
423065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
423165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
423265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
423365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
423465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashInit(MacroAssembler* masm,
423565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register hash,
423665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register character,
423765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                    Register scratch) {
4238fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  // hash = (seed + character) + ((seed + character) << 10);
4239fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  if (Serializer::enabled()) {
4240594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
42412efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    __ SmiUntag(scratch);
4242fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ add(scratch, character);
4243fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ mov(hash, scratch);
4244fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ shl(scratch, 10);
4245fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ add(hash, scratch);
4246fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  } else {
4247f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    int32_t seed = masm->isolate()->heap()->HashSeed();
4248fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ lea(scratch, Operand(character, seed));
4249fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ shl(scratch, 10);
4250fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    __ lea(hash, Operand(scratch, character, times_1, seed));
4251fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org  }
425265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash ^= hash >> 6;
425365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, hash);
42542c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  __ shr(scratch, 6);
4255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ xor_(hash, scratch);
425665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
425765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
425865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
425965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
426065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                            Register hash,
426165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                            Register character,
426265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                            Register scratch) {
426365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += character;
4264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(hash, character);
426565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += hash << 10;
426665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, hash);
426765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ shl(scratch, 10);
4268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(hash, scratch);
426965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash ^= hash >> 6;
427065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, hash);
42712c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  __ shr(scratch, 6);
4272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ xor_(hash, scratch);
427365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
427465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
427565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
427665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashGetHash(MacroAssembler* masm,
427765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register hash,
427865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                       Register scratch) {
427965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += hash << 3;
428065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, hash);
428165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ shl(scratch, 3);
4282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(hash, scratch);
428365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash ^= hash >> 11;
428465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, hash);
42852c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org  __ shr(scratch, 11);
4286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ xor_(hash, scratch);
428765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // hash += hash << 15;
428865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch, hash);
428965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ shl(scratch, 15);
4290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(hash, scratch);
429165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4292f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ and_(hash, String::kHashBitMask);
42932c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org
429465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // if (hash == 0) hash = 27;
429583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label hash_not_zero;
429683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_zero, &hash_not_zero, Label::kNear);
4297f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ mov(hash, Immediate(StringHasher::kZeroHash));
429865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&hash_not_zero);
429965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
430065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
430165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
430265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid SubStringStub::Generate(MacroAssembler* masm) {
430365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime;
430465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
430565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack frame on entry.
430665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[0]: return address
430765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[4]: to
430865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[8]: from
430965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[12]: string
431065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
431165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Make sure first argument is a string.
431265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, 3 * kPointerSize));
431365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
43147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(eax, &runtime);
431565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
431665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ j(NegateCondition(is_string), &runtime);
431765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
431865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: string
431965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ebx: instance type
432065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
432165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Calculate length of sub string using the smi values.
432265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(ecx, Operand(esp, 1 * kPointerSize));  // To index.
43237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(ecx, &runtime);
432465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, Operand(esp, 2 * kPointerSize));  // From index.
43257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(edx, &runtime);
4326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(ecx, edx);
432765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ cmp(ecx, FieldOperand(eax, String::kLengthOffset));
432864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label not_original_string;
4329ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Shorter than original string's length: an actual substring.
4330ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  __ j(below, &not_original_string, Label::kNear);
4331ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Longer than original string's length or negative: unsafe arguments.
4332ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  __ j(above, &runtime);
4333ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Return original string.
433464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Counters* counters = masm->isolate()->counters();
433564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ IncrementCounter(counters->sub_string_native(), 1);
433664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ret(3 * kPointerSize);
433764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&not_original_string);
433864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
43392e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  Label single_char;
43402e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ cmp(ecx, Immediate(Smi::FromInt(1)));
43412e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ j(equal, &single_char);
43422e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org
434364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // eax: string
434464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // ebx: instance type
434564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // ecx: sub string length (smi)
434664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // edx: from index (smi)
434764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Deal with different string types: update the index if necessary
434864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // and put the underlying string into edi.
434964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label underlying_unpacked, sliced_string, seq_or_external_string;
435064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // If the string is not indirect, it can only be sequential or external.
435164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
435264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  STATIC_ASSERT(kIsIndirectStringMask != 0);
435364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test(ebx, Immediate(kIsIndirectStringMask));
435464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(zero, &seq_or_external_string, Label::kNear);
435564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
435664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Factory* factory = masm->isolate()->factory();
435764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test(ebx, Immediate(kSlicedNotConsMask));
435864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_zero, &sliced_string, Label::kNear);
435964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Cons string.  Check whether it is flat, then fetch first part.
436064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Flat cons strings have an empty second part.
436164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
436264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org         factory->empty_string());
436364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &runtime);
436464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
436564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Update instance type.
436664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
436764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
436864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ jmp(&underlying_unpacked, Label::kNear);
436964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
437064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&sliced_string);
437164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Sliced string.  Fetch parent and adjust start index by offset.
437264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
437364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
437464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Update instance type.
437564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
437664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
437764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ jmp(&underlying_unpacked, Label::kNear);
437864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
437964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&seq_or_external_string);
438064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Sequential or external string.  Just move string to the expected register.
438164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(edi, eax);
438264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
438364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&underlying_unpacked);
438465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
438580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  if (FLAG_string_slices) {
438680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    Label copy_routine;
438780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // edi: underlying subject string
43887ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org    // ebx: instance type of underlying subject string
438964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // edx: adjusted start index (smi)
439064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // ecx: length (smi)
439164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ cmp(ecx, Immediate(Smi::FromInt(SlicedString::kMinLength)));
439264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Short slice.  Copy instead of slicing.
439364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ j(less, &copy_routine);
439480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // Allocate new sliced string.  At this point we do not reload the instance
439580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // type including the string encoding because we simply rely on the info
439680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // provided by the original string.  It does not matter if the original
439780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // string's encoding is wrong because we always have to recheck encoding of
439880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // the newly created string's parent anyways due to externalized strings.
439980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    Label two_byte_slice, set_slice_header;
4400e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org    STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
44011805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
44021805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    __ test(ebx, Immediate(kStringEncodingMask));
440380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ j(zero, &two_byte_slice, Label::kNear);
440480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ AllocateAsciiSlicedString(eax, ebx, no_reg, &runtime);
440580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ jmp(&set_slice_header, Label::kNear);
440680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ bind(&two_byte_slice);
44071805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime);
440880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ bind(&set_slice_header);
440980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx);
441080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset),
441180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org           Immediate(String::kEmptyHashField));
4412bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi);
4413bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx);
441464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ IncrementCounter(counters->sub_string_native(), 1);
441564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ ret(3 * kPointerSize);
441680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org
441780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    __ bind(&copy_routine);
441880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  }
441980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org
442064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // edi: underlying subject string
44217ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org  // ebx: instance type of underlying subject string
442264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // edx: adjusted start index (smi)
442364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // ecx: length (smi)
442464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // The subject string can only be external or sequential string of either
442564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // encoding at this point.
442664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label two_byte_sequential, runtime_drop_two, sequential_string;
442764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  STATIC_ASSERT(kExternalStringTag != 0);
442864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  STATIC_ASSERT(kSeqStringTag == 0);
442964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test_b(ebx, kExternalStringTag);
443064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(zero, &sequential_string);
443164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
443264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Handle external string.
443364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Rule out short external strings.
443464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  STATIC_CHECK(kShortExternalStringTag != 0);
443564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test_b(ebx, kShortExternalStringMask);
443664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_zero, &runtime);
443764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset));
443864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Move the pointer so that offset-wise, it looks like a sequential string.
4439fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
444064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
444165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
444264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&sequential_string);
444364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Stash away (adjusted) index and (underlying) string.
444464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ push(edx);
444564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ push(edi);
444664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ SmiUntag(ecx);
4447e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
444864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ test_b(ebx, kStringEncodingMask);
444964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(zero, &two_byte_sequential);
445064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
44512efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Sequential ASCII string.  Allocate the result.
445264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
445365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
445465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
445565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: result string length
445665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, esi);  // esi used by following code.
445765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate first character of result.
445865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, eax);
4459fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag));
446065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load string argument and locate character of sub string start.
446164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ pop(esi);
446264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ pop(ebx);
446365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ SmiUntag(ebx);
4464fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ lea(esi, FieldOperand(esi, ebx, times_1, SeqOneByteString::kHeaderSize));
446565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
446665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
446765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: result length
446865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: original value of esi
446965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: first character of result
447065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esi: character of sub string start
447165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
447265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(esi, edx);  // Restore esi.
44737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->sub_string_native(), 1);
447465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(3 * kPointerSize);
447565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
447664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&two_byte_sequential);
447764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Sequential two-byte string.  Allocate the result.
447864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
447965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
448065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
448165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: result string length
448265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, esi);  // esi used by following code.
448365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Locate first character of result.
448465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edi, eax);
4485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edi,
448665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org         Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
448765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load string argument and locate character of sub string start.
448864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ pop(esi);
448964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ pop(ebx);
449065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // As from is a smi it is 2 times the value which matches the size of a two
449165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // byte character.
449265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
449365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
449464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ lea(esi, FieldOperand(esi, ebx, times_1, SeqTwoByteString::kHeaderSize));
449565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
449665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // eax: result string
449765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ecx: result length
449865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edx: original value of esi
449965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // edi: first character of result
450065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // esi: character of sub string start
450165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
450265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(esi, edx);  // Restore esi.
45037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->sub_string_native(), 1);
450465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(3 * kPointerSize);
450565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
450664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Drop pushed values on the stack before tail call.
450764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&runtime_drop_two);
450864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ Drop(2);
450964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
451065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Just jump to runtime to create the sub string.
451165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
451265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kSubString, 3, 1);
45132e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org
45142e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ bind(&single_char);
45152e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // eax: string
45162e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // ebx: instance type
45172e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // ecx: sub string length (smi)
45182e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  // edx: from index (smi)
45192e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  StringCharAtGenerator generator(
45202e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org      eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
45212e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  generator.GenerateFast(masm);
45222e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  __ ret(3 * kPointerSize);
45232e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org  generator.SkipSlow(masm, &runtime);
452465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
452565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
452665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
45271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
45281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register left,
45291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register right,
45301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register scratch1,
45311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                                                      Register scratch2) {
45321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register length = scratch1;
45331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
45341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare lengths.
453583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label strings_not_equal, check_zero_length;
45361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(length, FieldOperand(left, String::kLengthOffset));
45371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ cmp(length, FieldOperand(right, String::kLengthOffset));
453883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(equal, &check_zero_length, Label::kNear);
45391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&strings_not_equal);
45401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Set(eax, Immediate(Smi::FromInt(NOT_EQUAL)));
45411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ret(0);
45421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
45431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check if the length is zero.
454483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label compare_chars;
45451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&check_zero_length);
45461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kSmiTag == 0);
4547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(length, length);
454883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_zero, &compare_chars, Label::kNear);
45491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
45501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ret(0);
45511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
45521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare characters.
45531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&compare_chars);
45541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
455583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                &strings_not_equal, Label::kNear);
45561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
45571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Characters are equal.
45581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
45591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ret(0);
45601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
45611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
45621c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
456365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
456465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register left,
456565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register right,
456665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch1,
456765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch2,
456865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                                        Register scratch3) {
45697979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Counters* counters = masm->isolate()->counters();
45707979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(counters->string_compare_native(), 1);
457165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
457265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Find minimum length.
457383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label left_shorter;
457465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
457565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(scratch3, scratch1);
457665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
457765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
457865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register length_delta = scratch3;
457965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
458083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(less_equal, &left_shorter, Label::kNear);
458165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Right string is shorter. Change scratch1 to be length of right string.
4582c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(scratch1, length_delta);
458365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&left_shorter);
458465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
458565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Register min_length = scratch1;
458665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
458765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // If either length is zero, just compare lengths.
458883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label compare_lengths;
4589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(min_length, min_length);
459083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(zero, &compare_lengths, Label::kNear);
459165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
45921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare characters.
459383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label result_not_equal;
45941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
459583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                                &result_not_equal, Label::kNear);
459665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
459765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Compare lengths -  strings up to min-length are equal.
459865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&compare_lengths);
4599c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(length_delta, length_delta);
460059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  Label length_not_equal;
460159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ j(not_zero, &length_not_equal, Label::kNear);
460265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
460365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result is EQUAL.
460465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(EQUAL == 0);
460565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
460665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
460765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
460865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
460983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label result_greater;
461059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  Label result_less;
461159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ bind(&length_not_equal);
461259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ j(greater, &result_greater, Label::kNear);
461359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ jmp(&result_less, Label::kNear);
461465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&result_not_equal);
461559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ j(above, &result_greater, Label::kNear);
461659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ bind(&result_less);
461765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
461865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result is LESS.
461965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Set(eax, Immediate(Smi::FromInt(LESS)));
462065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
462165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
462265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Result is GREATER.
462365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&result_greater);
462465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Set(eax, Immediate(Smi::FromInt(GREATER)));
462565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(0);
462665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
462765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
462865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
46291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid StringCompareStub::GenerateAsciiCharsCompareLoop(
46301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    MacroAssembler* masm,
46311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register left,
46321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register right,
46331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register length,
46341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Register scratch,
463583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label* chars_not_equal,
463683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label::Distance chars_not_equal_near) {
46371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Change index to run from -length to -1 by adding length to string
46381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // start. This means that loop ends when index reaches zero, which
46391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // doesn't need an additional compare.
46401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ SmiUntag(length);
46411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ lea(left,
4642fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize));
46431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ lea(right,
4644fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize));
46451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ neg(length);
46461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register index = length;  // index = -length;
46471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
46481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare loop.
464983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label loop;
46501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&loop);
46511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov_b(scratch, Operand(left, index, times_1, 0));
46521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ cmpb(scratch, Operand(right, index, times_1, 0));
465383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, chars_not_equal, chars_not_equal_near);
46544efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  __ inc(index);
46551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ j(not_zero, &loop);
46561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
46571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
46581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
465965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCompareStub::Generate(MacroAssembler* masm) {
466065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label runtime;
466165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
466265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Stack frame on entry.
466365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[0]: return address
466465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[4]: right string
466565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  //  esp[8]: left string
466665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
466765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(edx, Operand(esp, 2 * kPointerSize));  // left
466865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ mov(eax, Operand(esp, 1 * kPointerSize));  // right
466965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
467083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label not_same;
4671c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(edx, eax);
467283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &not_same, Label::kNear);
467365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(EQUAL == 0);
467465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  STATIC_ASSERT(kSmiTag == 0);
467565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
46767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1);
467765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ ret(2 * kPointerSize);
467865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
467965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&not_same);
468065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
46812efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Check that both objects are sequential ASCII strings.
468265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
468365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
46842efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Compare flat ASCII strings.
468565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Drop arguments from the stack.
468665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ pop(ecx);
4687c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(esp, Immediate(2 * kPointerSize));
468865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ push(ecx);
468965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi);
469065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
469165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
469265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // tagged as a small integer.
469365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ bind(&runtime);
469465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
469565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
469665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4697a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4698a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid ICCompareStub::GenerateSmis(MacroAssembler* masm) {
4699fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(state_ == CompareIC::SMI);
470083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label miss;
4701c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(ecx, edx);
4702c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ or_(ecx, eax);
47037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfNotSmi(ecx, &miss, Label::kNear);
4704a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4705a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  if (GetCondition() == equal) {
4706a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // For equality we do not care about the sign of the result.
4707c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(eax, edx);
4708a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  } else {
470983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label done;
4710c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(edx, eax);
471183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(no_overflow, &done, Label::kNear);
4712a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Correct sign of result in case of overflow.
4713a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ not_(edx);
4714a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ bind(&done);
4715a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(eax, edx);
4716a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
4717a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ret(0);
4718a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4719a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
4720a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GenerateMiss(masm);
4721a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
4722a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4723a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
47248432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
47258432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  ASSERT(state_ == CompareIC::NUMBER);
4726a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
472783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label generic_stub;
47289a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  Label unordered, maybe_undefined1, maybe_undefined2;
472983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label miss;
4730a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4731fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (left_ == CompareIC::SMI) {
4732fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(edx, &miss);
4733fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
4734fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  if (right_ == CompareIC::SMI) {
4735fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfNotSmi(eax, &miss);
4736fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  }
4737a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4738a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Inlining the double comparison and falling back to the general compare
4739fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  // stub if NaN is involved or SSE2 or CMOV is unsupported.
4740c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) {
4741750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope1(masm, SSE2);
4742750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    CpuFeatureScope scope2(masm, CMOV);
4743a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4744fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Load left and right operand.
4745fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    Label done, left, left_smi, right_smi;
4746fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(eax, &right_smi, Label::kNear);
4747fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
4748fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org           masm->isolate()->factory()->heap_number_map());
4749fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(not_equal, &maybe_undefined1, Label::kNear);
47500fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
4751fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ jmp(&left, Label::kNear);
4752fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&right_smi);
4753fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(ecx, eax);  // Can't clobber eax because we can still jump away.
4754fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ SmiUntag(ecx);
4755528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    __ Cvtsi2sd(xmm1, ecx);
4756fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
4757fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&left);
4758fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(edx, &left_smi, Label::kNear);
4759fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
4760fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org           masm->isolate()->factory()->heap_number_map());
4761fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(not_equal, &maybe_undefined2, Label::kNear);
47620fdb2a65d0f07bb7f6d6ce2f8337e00e5c9c323dbmeurer@chromium.org    __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
4763fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ jmp(&done);
4764fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&left_smi);
4765fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(ecx, edx);  // Can't clobber edx because we can still jump away.
4766fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ SmiUntag(ecx);
4767528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    __ Cvtsi2sd(xmm0, ecx);
4768a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4769fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ bind(&done);
4770fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    // Compare operands.
4771a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ ucomisd(xmm0, xmm1);
4772a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4773a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Don't base result on EFLAGS when a NaN is involved.
47747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ j(parity_even, &unordered, Label::kNear);
4775a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4776a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Return a result of -1, 0, or 1, based on EFLAGS.
4777a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    // Performing mov, because xor would destroy the flag register.
4778a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(eax, 0);  // equal
4779a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(ecx, Immediate(Smi::FromInt(1)));
4780c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmov(above, eax, ecx);
4781a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(ecx, Immediate(Smi::FromInt(-1)));
4782c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmov(below, eax, ecx);
4783a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ ret(0);
4784fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  } else {
4785fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ mov(ecx, edx);
4786fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ and_(ecx, eax);
4787fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(ecx, &generic_stub, Label::kNear);
4788fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org
4789fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
4790fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org           masm->isolate()->factory()->heap_number_map());
4791fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(not_equal, &maybe_undefined1, Label::kNear);
4792fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
4793fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org           masm->isolate()->factory()->heap_number_map());
4794fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ j(not_equal, &maybe_undefined2, Label::kNear);
4795a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
4796a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
47979a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  __ bind(&unordered);
4798a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&generic_stub);
4799fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ICCompareStub stub(op_, CompareIC::GENERIC, CompareIC::GENERIC,
4800fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                     CompareIC::GENERIC);
48018432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ jmp(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
4802a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
48039a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  __ bind(&maybe_undefined1);
48049a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  if (Token::IsOrderedRelationalCompareOp(op_)) {
48059a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ cmp(eax, Immediate(masm->isolate()->factory()->undefined_value()));
48069a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ j(not_equal, &miss);
4807fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org    __ JumpIfSmi(edx, &unordered);
48089a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
48099a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ j(not_equal, &maybe_undefined2, Label::kNear);
48109a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ jmp(&unordered);
48119a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  }
48129a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
48139a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  __ bind(&maybe_undefined2);
48149a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  if (Token::IsOrderedRelationalCompareOp(op_)) {
48159a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ cmp(edx, Immediate(masm->isolate()->factory()->undefined_value()));
48169a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org    __ j(equal, &unordered);
48179a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org  }
48189a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
4819a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
4820a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GenerateMiss(masm);
4821a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
4822a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4823a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
48244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
48254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(state_ == CompareIC::INTERNALIZED_STRING);
482683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(GetCondition() == equal);
482783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
482883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Registers containing left and right operands respectively.
482983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register left = edx;
483083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register right = eax;
483183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register tmp1 = ecx;
483283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Register tmp2 = ebx;
483383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
483483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Check that both operands are heap objects.
483583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label miss;
4836c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(tmp1, left);
483783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  STATIC_ASSERT(kSmiTag == 0);
4838c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ and_(tmp1, right);
48397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(tmp1, &miss, Label::kNear);
484083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
48414a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both operands are internalized strings.
484283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
484383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
484483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
484583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
4846ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
4847ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ or_(tmp1, tmp2);
4848ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ test(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
4849ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  __ j(not_zero, &miss, Label::kNear);
485083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
48514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Internalized strings are compared by identity.
48524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label done;
48534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ cmp(left, right);
48544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Make sure eax is non-zero. At this point input operands are
48554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // guaranteed to be non-zero.
48564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(right.is(eax));
48574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ j(not_equal, &done, Label::kNear);
48584a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  STATIC_ASSERT(EQUAL == 0);
48594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
48604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
48614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&done);
48624a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ ret(0);
48634a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ bind(&miss);
48654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  GenerateMiss(masm);
48664a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org}
48674a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) {
48704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(state_ == CompareIC::UNIQUE_NAME);
48714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  ASSERT(GetCondition() == equal);
48724a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Registers containing left and right operands respectively.
48744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register left = edx;
48754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register right = eax;
48764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register tmp1 = ecx;
48774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Register tmp2 = ebx;
48784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both operands are heap objects.
48804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  Label miss;
48814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(tmp1, left);
48824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0);
48834a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ and_(tmp1, right);
48844a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ JumpIfSmi(tmp1, &miss, Label::kNear);
48854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both operands are unique names. This leaves the instance
48874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // types loaded in tmp1 and tmp2.
48884a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
48894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
48904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
48914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
48924a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48931510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ JumpIfNotUniqueName(tmp1, &miss, Label::kNear);
48941510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ JumpIfNotUniqueName(tmp2, &miss, Label::kNear);
48954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org
48964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Unique names are compared by identity.
489783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
4898c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(left, right);
489983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // Make sure eax is non-zero. At this point input operands are
490083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  // guaranteed to be non-zero.
490183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  ASSERT(right.is(eax));
490283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &done, Label::kNear);
490383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  STATIC_ASSERT(EQUAL == 0);
490483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  STATIC_ASSERT(kSmiTag == 0);
490583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
490683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ bind(&done);
490783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ ret(0);
490883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
490983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ bind(&miss);
491083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  GenerateMiss(masm);
491183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org}
491283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
491383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org
49141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid ICCompareStub::GenerateStrings(MacroAssembler* masm) {
4915fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(state_ == CompareIC::STRING);
49161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label miss;
49171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49184efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  bool equality = Token::IsEqualityOp(op_);
49194efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
49201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Registers containing left and right operands respectively.
49211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register left = edx;
49221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register right = eax;
49231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp1 = ecx;
49241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp2 = ebx;
49251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register tmp3 = edi;
49261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check that both operands are heap objects.
4928c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(tmp1, left);
49291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kSmiTag == 0);
4930c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ and_(tmp1, right);
49317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(tmp1, &miss);
49321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check that both operands are strings. This leaves the instance
49341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // types loaded in tmp1 and tmp2.
49351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
49361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
49371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
49381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
49391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(tmp3, tmp1);
49401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kNotStringTag != 0);
4941c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ or_(tmp3, tmp2);
49421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ test(tmp3, Immediate(kIsNotStringMask));
49431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ j(not_zero, &miss);
49441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Fast check for identical strings.
494683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label not_same;
4947c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(left, right);
494883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &not_same, Label::kNear);
49491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(EQUAL == 0);
49501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  STATIC_ASSERT(kSmiTag == 0);
49511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
49521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ret(0);
49531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Handle not identical strings.
49551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&not_same);
49561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Check that both strings are internalized. If they are, we're done
49584efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  // because we already know they are not identical.  But in the case of
49591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // non-equality compare, we still need to determine the order. We
49601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // also know they are both strings.
49614efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (equality) {
49624efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    Label do_compare;
4963ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    STATIC_ASSERT(kInternalizedTag == 0);
4964ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ or_(tmp1, tmp2);
4965ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ test(tmp1, Immediate(kIsNotInternalizedMask));
4966ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    __ j(not_zero, &do_compare, Label::kNear);
49674efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    // Make sure eax is non-zero. At this point input operands are
49684efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    // guaranteed to be non-zero.
49694efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    ASSERT(right.is(eax));
49704efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ ret(0);
49714efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ bind(&do_compare);
49724efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
49731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49741c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Check that both strings are sequential ASCII.
49751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label runtime;
49761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
49771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Compare flat ASCII strings. Returns when done.
49794efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (equality) {
49804efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    StringCompareStub::GenerateFlatAsciiStringEquals(
49814efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org        masm, left, right, tmp1, tmp2);
49824efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  } else {
49834efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    StringCompareStub::GenerateCompareFlatAsciiStrings(
49844efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org        masm, left, right, tmp1, tmp2, tmp3);
49854efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
49861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Handle more complex cases in runtime.
49881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&runtime);
49891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ pop(tmp1);  // Return address.
49901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ push(left);
49911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ push(right);
49921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ push(tmp1);
49934efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (equality) {
49944efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
49954efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  } else {
49964efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
49974efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
49981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
49991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&miss);
50001c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  GenerateMiss(masm);
50011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
50021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
50031c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
5004a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid ICCompareStub::GenerateObjects(MacroAssembler* masm) {
5005fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  ASSERT(state_ == CompareIC::OBJECT);
500683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label miss;
5007c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(ecx, edx);
5008c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ and_(ecx, eax);
50097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  __ JumpIfSmi(ecx, &miss, Label::kNear);
5010a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5011a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
50127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(not_equal, &miss, Label::kNear);
5013a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
50147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(not_equal, &miss, Label::kNear);
5015a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5016a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  ASSERT(GetCondition() == equal);
5017c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(eax, edx);
5018a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ret(0);
5019a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5020a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&miss);
5021a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GenerateMiss(masm);
5022a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
5023a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5024a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
502564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
502664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Label miss;
502764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(ecx, edx);
502864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ and_(ecx, eax);
502964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ JumpIfSmi(ecx, &miss, Label::kNear);
503064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
503164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
503264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
503364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmp(ecx, known_map_);
503464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &miss, Label::kNear);
503564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ cmp(ebx, known_map_);
503664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ j(not_equal, &miss, Label::kNear);
503764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
503864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ sub(eax, edx);
503964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ ret(0);
5040a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
504164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  __ bind(&miss);
504264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  GenerateMiss(masm);
504364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org}
504464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
504564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
504664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid ICCompareStub::GenerateMiss(MacroAssembler* masm) {
5047c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
5048c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Call the runtime system in a fresh internal frame.
5049c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss),
5050c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                               masm->isolate());
5051c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm, StackFrame::INTERNAL);
505264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ push(edx);  // Preserve edx and eax.
505364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ push(eax);
505464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ push(edx);  // And also use them as the arguments.
5055c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(eax);
5056c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ push(Immediate(Smi::FromInt(op_)));
5057c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallExternalReference(miss, 3);
505864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    // Compute the entry point of the rewritten stub.
505964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ lea(edi, FieldOperand(eax, Code::kHeaderSize));
506064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(eax);
506164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    __ pop(edx);
5062c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5063a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5064a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Do a tail call to the rewritten stub.
5065c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ jmp(edi);
5066a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
5067a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5068a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
50691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// Helper function used to check that the dictionary doesn't contain
50701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// the property. This function may return false negatives, so miss_label
50711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// must always call a backup property check that is complete.
50721c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// This function is safe to call if the receiver has fast properties.
5073750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Name must be a unique name and receiver must be a heap object.
5074750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
5075750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* miss,
5076750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* done,
5077750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register properties,
5078750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Handle<Name> name,
5079750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register r0) {
5080750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  ASSERT(name->IsUniqueName());
5081394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5082394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // If names of slots in range from 1 to kProbes - 1 for the hash value are
5083394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // not equal to the name and kProbes-th slot is not used (its name is the
5084394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // undefined value), it guarantees the hash table doesn't contain the
5085394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // property. It's true even if some slots represent deleted properties
5086967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org  // (their names are the hole value).
5087394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  for (int i = 0; i < kInlinedProbes; i++) {
5088394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Compute the masked index: (hash + i + i * i) & mask.
5089394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Register index = r0;
5090394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Capacity is smi 2^n.
5091394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ mov(index, FieldOperand(properties, kCapacityOffset));
5092394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ dec(index);
5093394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ and_(index,
5094394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com            Immediate(Smi::FromInt(name->Hash() +
5095750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                   NameDictionary::GetProbeOffset(i))));
5096394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5097394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Scale the index by multiplying by the entry size.
5098750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    ASSERT(NameDictionary::kEntrySize == 3);
5099394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ lea(index, Operand(index, index, times_2, 0));  // index *= 3.
5100394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Register entity_name = r0;
5101394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Having undefined at this place means the name is not contained.
5102394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    ASSERT_EQ(kSmiTagSize, 1);
5103394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
5104394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                kElementsStartOffset - kHeapObjectTag));
5105394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
5106394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ j(equal, done);
5107394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5108394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Stop if found the property.
5109750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ cmp(entity_name, Handle<Name>(name));
5110394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ j(equal, miss);
5111394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5112750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    Label good;
5113967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org    // Check for the hole and skip.
5114967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org    __ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
5115750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ j(equal, &good, Label::kNear);
5116967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org
5117750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    // Check if the entry name is not a unique name.
5118394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
51191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ JumpIfNotUniqueName(FieldOperand(entity_name, Map::kInstanceTypeOffset),
51201510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                           miss);
5121750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ bind(&good);
5122394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
5123394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5124750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
5125394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(Immediate(Handle<Object>(name)));
5126394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ push(Immediate(name->Hash()));
5127394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ CallStub(&stub);
5128394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ test(r0, r0);
5129394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(not_zero, miss);
5130394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ jmp(done);
5131394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com}
5132394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5133394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
5134750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Probe the name dictionary in the |elements| register. Jump to the
51351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// |done| label if a property with the given name is found leaving the
51361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// index into the dictionary in |r0|. Jump to the |miss| label
51371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// otherwise.
5138750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
5139750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* miss,
5140750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Label* done,
5141750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register elements,
5142750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register name,
5143750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register r0,
5144750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org                                                      Register r1) {
51456e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!elements.is(r0));
51466e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!elements.is(r1));
51476e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!name.is(r0));
51486e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com  ASSERT(!name.is(r1));
51496e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com
5150750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ AssertName(name);
51511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
51521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(r1, FieldOperand(elements, kCapacityOffset));
51531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ shr(r1, kSmiTagSize);  // convert smi to int
51541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ dec(r1);
51551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
51561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Generate an unrolled loop that performs a few probes before
51571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // giving up. Measurements done on Gmail indicate that 2 probes
51581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // cover ~93% of loads from dictionaries.
51591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  for (int i = 0; i < kInlinedProbes; i++) {
51601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Compute the masked index: (hash + i + i * i) & mask.
5161750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
5162750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    __ shr(r0, Name::kHashShift);
51631c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (i > 0) {
5164750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      __ add(r0, Immediate(NameDictionary::GetProbeOffset(i)));
51651c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
5166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ and_(r0, r1);
51671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
51681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Scale the index by multiplying by the entry size.
5169750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    ASSERT(NameDictionary::kEntrySize == 3);
51701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ lea(r0, Operand(r0, r0, times_2, 0));  // r0 = r0 * 3
51711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
51721c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Check if the key is identical to the name.
51731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ cmp(name, Operand(elements,
51741c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                         r0,
51751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                         times_4,
51761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                         kElementsStartOffset - kHeapObjectTag));
51777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ j(equal, done);
51781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
51791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
5180750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  NameDictionaryLookupStub stub(elements, r1, r0, POSITIVE_LOOKUP);
51811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ push(name);
5182750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
5183750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  __ shr(r0, Name::kHashShift);
51841c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ push(r0);
51851c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ CallStub(&stub);
51861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
5187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(r1, r1);
51881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ j(zero, miss);
51891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ jmp(done);
51901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
51911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
51921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
5193750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
5194c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
5195c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // we cannot call anything that could cause a GC from this stub.
51961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Stack frame on entry:
51971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  esp[0 * kPointerSize]: return address.
51981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  esp[1 * kPointerSize]: key's hash.
51991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  esp[2 * kPointerSize]: key.
52001c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Registers:
5201750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  //  dictionary_: NameDictionary to probe.
52021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  result_: used as scratch.
52031c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  index_: will hold an index of entry if lookup is successful.
52041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //          might alias with result_.
52051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // Returns:
52061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  //  result_ is zero if lookup failed, non zero otherwise.
52071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
52091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Register scratch = result_;
52111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(scratch, FieldOperand(dictionary_, kCapacityOffset));
52131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ dec(scratch);
52141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ SmiUntag(scratch);
52151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ push(scratch);
52161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // If names of slots in range from 1 to kProbes - 1 for the hash value are
52181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // not equal to the name and kProbes-th slot is not used (its name is the
52191c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // undefined value), it guarantees the hash table doesn't contain the
52201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // property. It's true even if some slots represent deleted properties
52211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // (their names are the null value).
52221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  for (int i = kInlinedProbes; i < kTotalProbes; i++) {
52231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Compute the masked index: (hash + i + i * i) & mask.
52241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ mov(scratch, Operand(esp, 2 * kPointerSize));
52251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (i > 0) {
5226750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      __ add(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
52271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
52281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ and_(scratch, Operand(esp, 0));
52291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Scale the index by multiplying by the entry size.
5231750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org    ASSERT(NameDictionary::kEntrySize == 3);
52321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ lea(index_, Operand(scratch, scratch, times_2, 0));  // index *= 3.
52331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Having undefined at this place means the name is not contained.
52351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    ASSERT_EQ(kSmiTagSize, 1);
52361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ mov(scratch, Operand(dictionary_,
52371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                            index_,
52381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                            times_pointer_size,
52391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org                            kElementsStartOffset - kHeapObjectTag));
52401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ cmp(scratch, masm->isolate()->factory()->undefined_value());
52411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ j(equal, &not_in_dictionary);
52421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    // Stop if found the property.
52441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ cmp(scratch, Operand(esp, 3 * kPointerSize));
52451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ j(equal, &in_dictionary);
52461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
5248750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      // If we hit a key that is not a unique name during negative
52494a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org      // lookup we have to bailout as this key might be equal to the
52501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // key we are looking for.
52511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
5252750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      // Check if the entry name is not a unique name.
52531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
52541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ JumpIfNotUniqueName(FieldOperand(scratch, Map::kInstanceTypeOffset),
52551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                             &maybe_in_dictionary);
52561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
52571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
52581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&maybe_in_dictionary);
52601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // If we are doing negative lookup then probing failure should be
52611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // treated as a lookup success. For positive lookup probing failure
52621c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  // should be treated as lookup failure.
52631c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  if (mode_ == POSITIVE_LOOKUP) {
52641c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ mov(result_, Immediate(0));
52651c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ Drop(1);
52661c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    __ ret(2 * kPointerSize);
52671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
52681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&in_dictionary);
52701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(result_, Immediate(1));
52711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Drop(1);
52721c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ret(2 * kPointerSize);
52731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52741c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ bind(&not_in_dictionary);
52751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ mov(result_, Immediate(0));
52761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ Drop(1);
52771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  __ ret(2 * kPointerSize);
52781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org}
52791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
52818432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
52828432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Isolate* isolate) {
5283750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  StoreBufferOverflowStub stub(kDontSaveFPRegs);
52848a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org  stub.GetCode(isolate);
5285750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org  if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
5286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    StoreBufferOverflowStub stub2(kSaveFPRegs);
52878a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    stub2.GetCode(isolate);
5288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
5290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
529233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgbool CodeStub::CanUseFPRegisters() {
529333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  return CpuFeatures::IsSupported(SSE2);
529433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org}
529533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
529633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
5297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Takes the input in 3 registers: address_ value_ and object_.  A pointer to
5298c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// the value has just been written into the object, now this stub makes sure
5299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// we keep the GC informed.  The word in the object where the value has been
5300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// written is in the address register.
5301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::Generate(MacroAssembler* masm) {
5302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label skip_to_incremental_noncompacting;
5303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label skip_to_incremental_compacting;
5304c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The first two instructions are generated with labels so as to get the
5306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // offset fixed up correctly by the bind(Label*) call.  We patch it back and
5307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // forth between a compare instructions (a nop in this position) and the
5308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // real branch when we start and stop incremental heap marking.
5309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ jmp(&skip_to_incremental_noncompacting, Label::kNear);
5310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ jmp(&skip_to_incremental_compacting, Label::kFar);
5311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
5313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
5314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
5315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
5316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
5317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
5318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
5319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ret(0);
5320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&skip_to_incremental_noncompacting);
5323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  GenerateIncremental(masm, INCREMENTAL);
5324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&skip_to_incremental_compacting);
5326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  GenerateIncremental(masm, INCREMENTAL_COMPACTION);
5327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
5329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Will be checked in IncrementalMarking::ActivateGeneratedStub.
5330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  masm->set_byte_at(0, kTwoByteNopInstruction);
5331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  masm->set_byte_at(2, kFiveByteNopInstruction);
5332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
5333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
5336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Save(masm);
5337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
5339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label dont_need_remembered_set;
5340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
5342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
5343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           regs_.scratch0(),
5344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           &dont_need_remembered_set);
5345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CheckPageFlag(regs_.object(),
5347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     regs_.scratch0(),
5348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     1 << MemoryChunk::SCAN_ON_SCAVENGE,
5349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     not_zero,
5350c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     &dont_need_remembered_set);
5351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // First notify the incremental marker if necessary, then update the
5353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // remembered set.
5354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    CheckNeedsToInformIncrementalMarker(
5355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        masm,
5356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        kUpdateRememberedSetOnNoNeedToInformIncrementalMarker,
5357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        mode);
5358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    InformIncrementalMarker(masm, mode);
5359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    regs_.Restore(masm);
5360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
5361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
5362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
5363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
5364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
5365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&dont_need_remembered_set);
5367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CheckNeedsToInformIncrementalMarker(
5370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      masm,
5371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      kReturnOnNoNeedToInformIncrementalMarker,
5372c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      mode);
5373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  InformIncrementalMarker(masm, mode);
5374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Restore(masm);
5375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ ret(0);
5376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
5377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5379c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) {
5380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
5381c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  int argument_count = 3;
5382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ PrepareCallCFunction(argument_count, regs_.scratch0());
5383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(Operand(esp, 0 * kPointerSize), regs_.object());
53848e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), regs_.address());  // Slot.
5385c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(Operand(esp, 2 * kPointerSize),
538632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org         Immediate(ExternalReference::isolate_address(masm->isolate())));
5387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  AllowExternalCallThatCantCauseGC scope(masm);
5389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (mode == INCREMENTAL_COMPACTION) {
5390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallCFunction(
5391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ExternalReference::incremental_evacuation_record_write_function(
5392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            masm->isolate()),
5393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        argument_count);
5394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
5395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(mode == INCREMENTAL);
5396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallCFunction(
5397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        ExternalReference::incremental_marking_record_write_function(
5398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com            masm->isolate()),
5399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        argument_count);
5400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
5402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
5403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker(
5406c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    MacroAssembler* masm,
5407c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    OnNoNeedToInformIncrementalMarker on_no_need,
5408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Mode mode) {
5409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label object_is_black, need_incremental, need_incremental_pop_object;
5410c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
541133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ mov(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask));
541233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ and_(regs_.scratch0(), regs_.object());
541333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ mov(regs_.scratch1(),
541433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org         Operand(regs_.scratch0(),
541533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                 MemoryChunk::kWriteBarrierCounterOffset));
541633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ sub(regs_.scratch1(), Immediate(1));
541733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ mov(Operand(regs_.scratch0(),
541833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                 MemoryChunk::kWriteBarrierCounterOffset),
541933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org         regs_.scratch1());
542033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  __ j(negative, &need_incremental);
542133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
5422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Let's look at the color of the object:  If it is not black we don't have
5423c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // to inform the incremental marker.
5424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ JumpIfBlack(regs_.object(),
5425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                 regs_.scratch0(),
5426c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                 regs_.scratch1(),
5427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                 &object_is_black,
5428c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                 Label::kNear);
5429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Restore(masm);
5431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
5432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
5433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
5434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
5435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
5436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
5437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
5438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ret(0);
5439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&object_is_black);
5442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Get the value from the slot.
5444c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
5445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (mode == INCREMENTAL_COMPACTION) {
5447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Label ensure_not_white;
5448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CheckPageFlag(regs_.scratch0(),  // Contains value.
5450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     regs_.scratch1(),  // Scratch.
5451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     MemoryChunk::kEvacuationCandidateMask,
5452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     zero,
5453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     &ensure_not_white,
5454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Label::kNear);
5455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CheckPageFlag(regs_.object(),
5457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     regs_.scratch1(),  // Scratch.
5458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     MemoryChunk::kSkipEvacuationSlotsRecordingMask,
5459c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     not_zero,
5460c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     &ensure_not_white,
5461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                     Label::kNear);
5462c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5463c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ jmp(&need_incremental);
5464c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5465c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ bind(&ensure_not_white);
5466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5467c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5468c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We need an extra register for this, so we push the object register
5469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // temporarily.
5470c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ push(regs_.object());
5471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ EnsureNotWhite(regs_.scratch0(),  // The value.
5472c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    regs_.scratch1(),  // Scratch.
5473c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    regs_.object(),  // Scratch.
5474c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    &need_incremental_pop_object,
5475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                    Label::kNear);
5476c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ pop(regs_.object());
5477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5478c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  regs_.Restore(masm);
5479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
5480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RememberedSetHelper(object_,
5481c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           address_,
5482c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           value_,
5483c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           save_fp_regs_mode_,
5484c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                           MacroAssembler::kReturnAtEnd);
5485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } else {
5486c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ ret(0);
5487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
5488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&need_incremental_pop_object);
5490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ pop(regs_.object());
5491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ bind(&need_incremental);
5493c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Fall through when we need to inform the incremental marker.
5495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
5496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5497c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5498c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
5499c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // ----------- S t a t e -------------
5500c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  //  -- eax    : element value to store
5501c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  //  -- ecx    : element index as smi
5502c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  //  -- esp[0] : return address
5503b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  //  -- esp[4] : array literal index in function
5504b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  //  -- esp[8] : array literal
5505b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // clobbers ebx, edx, edi
5506c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  // -----------------------------------
5507c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5508c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label element_done;
5509c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label double_elements;
5510c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label smi_element;
5511c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label slow_elements;
5512c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label slow_elements_from_double;
5513c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  Label fast_elements;
5514c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5515b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  // Get array literal index, array literal and its map.
5516b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ mov(edx, Operand(esp, 1 * kPointerSize));
5517b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ mov(ebx, Operand(esp, 2 * kPointerSize));
5518b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org  __ mov(edi, FieldOperand(ebx, JSObject::kMapOffset));
5519b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org
552004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ CheckFastElements(edi, &double_elements);
5521c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5522830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // Check for FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS elements
552304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ JumpIfSmi(eax, &smi_element);
5524830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  __ CheckFastSmiElements(edi, &fast_elements, Label::kNear);
5525c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
552604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Store into the array literal requires a elements transition. Call into
552704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // the runtime.
5528c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5529c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ bind(&slow_elements);
5530c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ pop(edi);  // Pop return address and remember to put back later for tail
5531c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                // call.
5532c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ push(ebx);
5533c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ push(ecx);
5534c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ push(eax);
5535c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
5536c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
5537c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ push(edx);
5538c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ push(edi);  // Return return address so that tail call returns to right
5539c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                 // place.
5540c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
5541c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
554204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&slow_elements_from_double);
554304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ pop(edx);
554404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ jmp(&slow_elements);
554504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
5546830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
554704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&fast_elements);
554804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
554904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size,
555004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                           FixedArrayBase::kHeaderSize));
555104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ mov(Operand(ecx, 0), eax);
555204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Update the write barrier for the array store.
555304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ RecordWrite(ebx, ecx, eax,
555404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                 kDontSaveFPRegs,
555504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                 EMIT_REMEMBERED_SET,
555604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                 OMIT_SMI_CHECK);
555704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ret(0);
5558c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5559830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS,
5560830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // and value is Smi.
556104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&smi_element);
556204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
556304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ mov(FieldOperand(ebx, ecx, times_half_pointer_size,
556404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                      FixedArrayBase::kHeaderSize), eax);
556504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ret(0);
5566c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5567830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS.
556804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ bind(&double_elements);
556904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
557004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ push(edx);
557104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset));
557204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ StoreNumberToDoubleElements(eax,
557304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                 edx,
557404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                 ecx,
557504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                 edi,
557604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                 xmm0,
557704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                 &slow_elements_from_double,
557804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org                                 false);
557904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ pop(edx);
558004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ ret(0);
5581c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org}
5582c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org
5583753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5584068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.orgvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
5585e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
55868432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org  __ call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
55872f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  int parameter_count_offset =
55882f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
55892f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  __ mov(ebx, MemOperand(ebp, parameter_count_offset));
5590068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org  masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
55912f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  __ pop(ecx);
5592f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
5593f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      ? kPointerSize
5594f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      : 0;
5595f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset));
55962f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org  __ jmp(ecx);  // Return to IC Miss stub, continuation still on stack.
5597068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org}
5598068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
5599068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org
5600ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.orgvoid StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) {
5601ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
5602ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  __ call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
5603ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  __ mov(edi, eax);
5604ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  int parameter_count_offset =
5605ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
5606ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  __ mov(eax, MemOperand(ebp, parameter_count_offset));
5607ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  // The parameter count above includes the receiver for the arguments passed to
5608ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  // the deoptimization handler. Subtract the receiver for the parameter count
5609ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  // for the call.
5610ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  __ sub(eax, Immediate(1));
5611ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
5612ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  ParameterCount argument_count(eax);
5613ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org  __ InvokeFunction(
5614ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org      edi, argument_count, JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
5615ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org}
5616ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org
5617ea468886ebe54afda9c81df0e85eea04bbb4f0f2machenbach@chromium.org
5618753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.orgvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
56191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  if (masm->isolate()->function_entry_hook() != NULL) {
5620753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    ProfileEntryHookStub stub;
5621753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org    masm->CallStub(&stub);
5622753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  }
5623753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org}
5624753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5625753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5626753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.orgvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) {
56271510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Save volatile registers.
56281510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  const int kNumSavedRegisters = 3;
56291510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ push(eax);
5630753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ push(ecx);
56311510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ push(edx);
5632753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5633753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Calculate and push the original stack pointer.
5634dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize));
5635753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ push(eax);
5636753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5637dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  // Retrieve our return address and use it to calculate the calling
5638dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  // function's address.
5639dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  __ mov(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize));
5640753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ sub(eax, Immediate(Assembler::kCallInstructionLength));
5641753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ push(eax);
5642753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5643753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Call the entry hook.
56441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  ASSERT(masm->isolate()->function_entry_hook() != NULL);
56451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ call(FUNCTION_ADDR(masm->isolate()->function_entry_hook()),
56461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org          RelocInfo::RUNTIME_ENTRY);
5647753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ add(esp, Immediate(2 * kPointerSize));
5648753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5649753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  // Restore ecx.
56501510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ pop(edx);
5651753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ pop(ecx);
56521510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ pop(eax);
56531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
5654753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ ret(0);
5655753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org}
5656753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
5657ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5658ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgtemplate<class T>
56594a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.orgstatic void CreateArrayDispatch(MacroAssembler* masm,
56604a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                AllocationSiteOverrideMode mode) {
56614a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  if (mode == DISABLE_ALLOCATION_SITES) {
56624a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    T stub(GetInitialFastElementsKind(),
56634a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org           CONTEXT_CHECK_REQUIRED,
56644a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org           mode);
5665ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ TailCallStub(&stub);
56664a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else if (mode == DONT_OVERRIDE) {
56674a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    int last_index = GetSequenceIndexFromFastElementsKind(
56684a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org        TERMINAL_FAST_ELEMENTS_KIND);
56694a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    for (int i = 0; i <= last_index; ++i) {
56704a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      Label next;
56714a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
56724a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ cmp(edx, kind);
56734a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ j(not_equal, &next);
56744a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      T stub(kind);
56754a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ TailCallStub(&stub);
56764a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ bind(&next);
56774a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    }
5678ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
56794a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    // If we reached this point there is a problem.
56804a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ Abort(kUnexpectedElementsKindInArrayConstructor);
56814a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else {
56824a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    UNREACHABLE();
56834a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  }
5684ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
5685ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5686ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
56874a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.orgstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm,
56884a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                           AllocationSiteOverrideMode mode) {
56894a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // ebx - type info cell (if mode != DISABLE_ALLOCATION_SITES)
56904a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // edx - kind (if mode != DISABLE_ALLOCATION_SITES)
5691ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // eax - number of arguments
5692ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // edi - constructor?
5693ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // esp[0] - return address
5694ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // esp[4] - last argument
5695ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  Label normal_sequence;
56964a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  if (mode == DONT_OVERRIDE) {
56974a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(FAST_SMI_ELEMENTS == 0);
56984a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
56994a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(FAST_ELEMENTS == 2);
57004a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(FAST_HOLEY_ELEMENTS == 3);
57014a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(FAST_DOUBLE_ELEMENTS == 4);
57024a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
57034a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
57044a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    // is the low bit set? If so, we are holey and that is good.
57054a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ test_b(edx, 1);
57064a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ j(not_zero, &normal_sequence);
57074a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  }
5708ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5709ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // look at the first argument
5710ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ mov(ecx, Operand(esp, kPointerSize));
5711ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ test(ecx, ecx);
5712ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ j(zero, &normal_sequence);
5713ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
57144a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  if (mode == DISABLE_ALLOCATION_SITES) {
57154a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ElementsKind initial = GetInitialFastElementsKind();
57164a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ElementsKind holey_initial = GetHoleyElementsKind(initial);
57171510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
57184a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ArraySingleArgumentConstructorStub stub_holey(holey_initial,
57194a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                                  CONTEXT_CHECK_REQUIRED,
57204a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                                  DISABLE_ALLOCATION_SITES);
57214a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ TailCallStub(&stub_holey);
5722ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
57234a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ bind(&normal_sequence);
57244a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    ArraySingleArgumentConstructorStub stub(initial,
57254a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                            CONTEXT_CHECK_REQUIRED,
57264a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org                                            DISABLE_ALLOCATION_SITES);
5727ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ TailCallStub(&stub);
57284a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else if (mode == DONT_OVERRIDE) {
57294a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    // We are going to create a holey array, but our kind is non-holey.
57304a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    // Fix kind and retry.
57314a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ inc(edx);
57324a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
57334a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    if (FLAG_debug_code) {
5734528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      Handle<Map> allocation_site_map =
5735528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org          masm->isolate()->factory()->allocation_site_map();
57364a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map));
57374a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ Assert(equal, kExpectedAllocationSiteInCell);
57384a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    }
57394a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
5740b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    // Save the resulting elements kind in type info. We can't just store r3
5741b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    // in the AllocationSite::transition_info field because elements kind is
5742b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    // restricted to a portion of the field...upper bits need to be left alone.
5743b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
5744b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org    __ add(FieldOperand(ecx, AllocationSite::kTransitionInfoOffset),
5745b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org           Immediate(Smi::FromInt(kFastElementsKindPackedToHoley)));
57464a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
57474a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ bind(&normal_sequence);
57484a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    int last_index = GetSequenceIndexFromFastElementsKind(
57494a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org        TERMINAL_FAST_ELEMENTS_KIND);
57504a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    for (int i = 0; i <= last_index; ++i) {
57514a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      Label next;
57524a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
57534a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ cmp(edx, kind);
57544a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ j(not_equal, &next);
57554a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      ArraySingleArgumentConstructorStub stub(kind);
57564a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ TailCallStub(&stub);
57574a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org      __ bind(&next);
57584a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    }
5759ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
57604a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    // If we reached this point there is a problem.
57614a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ Abort(kUnexpectedElementsKindInArrayConstructor);
57624a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else {
57634a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    UNREACHABLE();
57644a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  }
5765ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
5766ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5767ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5768ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgtemplate<class T>
5769ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
57704a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ElementsKind initial_kind = GetInitialFastElementsKind();
57714a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind);
57724a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
5773ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  int to_index = GetSequenceIndexFromFastElementsKind(
5774ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      TERMINAL_FAST_ELEMENTS_KIND);
5775ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  for (int i = 0; i <= to_index; ++i) {
5776ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
57771510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    T stub(kind);
57788a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    stub.GetCode(isolate);
57794a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE ||
57804a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org        (!FLAG_track_allocation_sites &&
57814a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org         (kind == initial_kind || kind == initial_holey_kind))) {
57821510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES);
57838a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org      stub1.GetCode(isolate);
5784d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    }
5785ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
5786ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
5787ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5788ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5789ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
5790ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
5791ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      isolate);
5792ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
5793ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      isolate);
5794ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
5795ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      isolate);
5796ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
5797ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5798ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5799d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
5800d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    Isolate* isolate) {
5801d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
5802d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  for (int i = 0; i < 2; i++) {
5803d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // For internal arrays we only need a few things
5804d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArrayNoArgumentConstructorStub stubh1(kinds[i]);
58058a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    stubh1.GetCode(isolate);
5806d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArraySingleArgumentConstructorStub stubh2(kinds[i]);
58078a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    stubh2.GetCode(isolate);
5808d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArrayNArgumentsConstructorStub stubh3(kinds[i]);
58098a58f6420f995bb19fff9babb261458d49d90cb1machenbach@chromium.org    stubh3.GetCode(isolate);
5810d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
5811d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
5812d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5813d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
58144a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.orgvoid ArrayConstructorStub::GenerateDispatchToArrayStub(
58154a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    MacroAssembler* masm,
58164a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    AllocationSiteOverrideMode mode) {
58174a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  if (argument_count_ == ANY) {
58184a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    Label not_zero_case, not_one_case;
58194a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ test(eax, eax);
58204a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ j(not_zero, &not_zero_case);
58214a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
58224a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
58234a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ bind(&not_zero_case);
58244a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ cmp(eax, 1);
58254a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ j(greater, &not_one_case);
58264a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    CreateArrayDispatchOneArgument(masm, mode);
58274a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
58284a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    __ bind(&not_one_case);
58294a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
58304a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else if (argument_count_ == NONE) {
58314a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
58324a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else if (argument_count_ == ONE) {
58334a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    CreateArrayDispatchOneArgument(masm, mode);
58344a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else if (argument_count_ == MORE_THAN_ONE) {
58354a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
58364a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  } else {
58374a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org    UNREACHABLE();
58384a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  }
58394a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org}
58404a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
58414a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
5842ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayConstructorStub::Generate(MacroAssembler* masm) {
5843ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // ----------- S t a t e -------------
5844ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- eax : argc (only if argument_count_ == ANY)
5845ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- ebx : type info cell
5846ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- edi : constructor
5847ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- esp[0] : return address
5848ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  //  -- esp[4] : last argument
5849ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // -----------------------------------
5850ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  Handle<Object> undefined_sentinel(
5851ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      masm->isolate()->heap()->undefined_value(),
5852ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org      masm->isolate());
5853ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5854ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  if (FLAG_debug_code) {
5855ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // The array construct code is only set for the global and natives
5856ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // builtin Array functions which always have maps.
5857ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5858ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // Initial map for the builtin Array function should be a map.
5859ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
5860ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    // Will both indicate a NULL and a Smi.
5861ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ test(ecx, Immediate(kSmiTagMask));
5862594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
5863ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ CmpObjectType(ecx, MAP_TYPE, ecx);
5864594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
5865ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
586641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    // We should either have undefined in ebx or a valid cell
5867ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Label okay_here;
586841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
5869ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ cmp(ebx, Immediate(undefined_sentinel));
5870ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ j(equal, &okay_here);
587141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    __ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
5872594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(equal, kExpectedPropertyCellInRegisterEbx);
5873ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ bind(&okay_here);
5874ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
5875ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
58764a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  Label no_info;
58774a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // If the type cell is undefined, or contains anything other than an
58784a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // AllocationSite, call an array constructor that doesn't use AllocationSites.
58791510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ cmp(ebx, Immediate(undefined_sentinel));
58801510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ j(equal, &no_info);
58811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ mov(edx, FieldOperand(ebx, Cell::kValueOffset));
5882528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  __ cmp(FieldOperand(edx, 0), Immediate(
5883528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      masm->isolate()->factory()->allocation_site_map()));
5884bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ j(not_equal, &no_info);
5885bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
5886b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  // Only look at the lower 16 bits of the transition info.
5887bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  __ mov(edx, FieldOperand(edx, AllocationSite::kTransitionInfoOffset));
58881510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ SmiUntag(edx);
5889b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
5890b5be0a91a2e75da55653dd3583b7f3c1c54f7309machenbach@chromium.org  __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask));
58914a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
58921510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
58934a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ bind(&no_info);
58944a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
5895ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
5896ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5897ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
5898d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStub::GenerateCase(
5899d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    MacroAssembler* masm, ElementsKind kind) {
5900d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Label not_zero_case, not_one_case;
5901d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Label normal_sequence;
5902d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5903d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ test(eax, eax);
5904d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ j(not_zero, &not_zero_case);
5905d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InternalArrayNoArgumentConstructorStub stub0(kind);
5906d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ TailCallStub(&stub0);
5907d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5908d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&not_zero_case);
5909d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ cmp(eax, 1);
5910d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ j(greater, &not_one_case);
5911d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5912d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  if (IsFastPackedElementsKind(kind)) {
5913d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // We might need to create a holey array
5914d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // look at the first argument
5915d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ mov(ecx, Operand(esp, kPointerSize));
5916d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ test(ecx, ecx);
5917d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ j(zero, &normal_sequence);
5918d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5919d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    InternalArraySingleArgumentConstructorStub
5920d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org        stub1_holey(GetHoleyElementsKind(kind));
5921d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ TailCallStub(&stub1_holey);
5922d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
5923d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5924d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&normal_sequence);
5925d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InternalArraySingleArgumentConstructorStub stub1(kind);
5926d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ TailCallStub(&stub1);
5927d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5928d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ bind(&not_one_case);
5929d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  InternalArrayNArgumentsConstructorStub stubN(kind);
5930d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ TailCallStub(&stubN);
5931d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
5932d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5933d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5934d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
5935d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // ----------- S t a t e -------------
5936d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- eax : argc
5937d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- ebx : type info cell
5938d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- edi : constructor
5939d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- esp[0] : return address
5940d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  //  -- esp[4] : last argument
5941d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  // -----------------------------------
5942d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5943d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  if (FLAG_debug_code) {
5944d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // The array construct code is only set for the global and natives
5945d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // builtin Array functions which always have maps.
5946d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5947d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // Initial map for the builtin Array function should be a map.
5948d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
5949d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    // Will both indicate a NULL and a Smi.
5950d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ test(ecx, Immediate(kSmiTagMask));
5951594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
5952d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ CmpObjectType(ecx, MAP_TYPE, ecx);
5953594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
5954d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  }
5955d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
59561510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Figure out the right elements kind
59571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
5958d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
59591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Load the map's "bit field 2" into |result|. We only need the first byte,
59601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // but the following masking takes care of that anyway.
59611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset));
59621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  // Retrieve elements_kind from bit field 2.
59631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ and_(ecx, Map::kElementsKindMask);
59641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ shr(ecx, Map::kElementsKindShift);
5965d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
59661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  if (FLAG_debug_code) {
59671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    Label done;
5968d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org    __ cmp(ecx, Immediate(FAST_ELEMENTS));
59691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ j(equal, &done);
59701510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS));
59711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ Assert(equal,
5972594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org              kInvalidElementsKindForInternalArrayOrInternalPackedArray);
59731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    __ bind(&done);
59741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  }
5975d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
59761510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Label fast_elements_case;
59771510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ cmp(ecx, Immediate(FAST_ELEMENTS));
59781510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ j(equal, &fast_elements_case);
59791510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  GenerateCase(masm, FAST_HOLEY_ELEMENTS);
5980d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
59811510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ bind(&fast_elements_case);
59821510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  GenerateCase(masm, FAST_ELEMENTS);
5983d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org}
5984d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
5985d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org
598665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#undef __
598765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
598865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} }  // namespace v8::internal
598965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
599065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif  // V8_TARGET_ARCH_IA32
5991