1fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Redistribution and use in source and binary forms, with or without 365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// modification, are permitted provided that the following conditions are 465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// met: 565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// 665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// * Redistributions of source code must retain the above copyright 765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// notice, this list of conditions and the following disclaimer. 865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// * Redistributions in binary form must reproduce the above 965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// copyright notice, this list of conditions and the following 1065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// disclaimer in the documentation and/or other materials provided 1165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// with the distribution. 1265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// * Neither the name of Google Inc. nor the names of its 1365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// contributors may be used to endorse or promote products derived 1465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// from this software without specific prior written permission. 1565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// 1665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 2865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "v8.h" 2965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_ARM 3165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "bootstrapper.h" 33d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org#include "code-stubs.h" 3465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#include "regexp-macro-assembler.h" 356bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org#include "stub-cache.h" 3665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace v8 { 3865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgnamespace internal { 3965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 41c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid ToNumberStub::InitializeInterfaceDescriptor( 42c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org Isolate* isolate, 43c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org CodeStubInterfaceDescriptor* descriptor) { 44c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org static Register registers[] = { r0 }; 45c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org descriptor->register_param_count_ = 1; 46c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org descriptor->register_params_ = registers; 47c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org descriptor->deoptimization_handler_ = NULL; 48c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org} 49c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 50c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org 51e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid FastCloneShallowArrayStub::InitializeInterfaceDescriptor( 52e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Isolate* isolate, 53e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org CodeStubInterfaceDescriptor* descriptor) { 54e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org static Register registers[] = { r3, r2, r1 }; 55e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org descriptor->register_param_count_ = 3; 56e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org descriptor->register_params_ = registers; 57e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org descriptor->deoptimization_handler_ = 58e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry; 59e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org} 60e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 61e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 6271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.orgvoid FastCloneShallowObjectStub::InitializeInterfaceDescriptor( 6371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org Isolate* isolate, 6471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org CodeStubInterfaceDescriptor* descriptor) { 6571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org static Register registers[] = { r3, r2, r1, r0 }; 6671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org descriptor->register_param_count_ = 4; 6771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org descriptor->register_params_ = registers; 6871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org descriptor->deoptimization_handler_ = 6971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; 7071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org} 7171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 7271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 73bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid CreateAllocationSiteStub::InitializeInterfaceDescriptor( 74bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org Isolate* isolate, 75bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org CodeStubInterfaceDescriptor* descriptor) { 76bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org static Register registers[] = { r2 }; 77bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org descriptor->register_param_count_ = 1; 78bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org descriptor->register_params_ = registers; 79bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org descriptor->deoptimization_handler_ = NULL; 80bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org} 81bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 82bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 83a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid KeyedLoadFastElementStub::InitializeInterfaceDescriptor( 84a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org Isolate* isolate, 85a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org CodeStubInterfaceDescriptor* descriptor) { 86a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org static Register registers[] = { r1, r0 }; 87a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org descriptor->register_param_count_ = 2; 88a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org descriptor->register_params_ = registers; 89a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org descriptor->deoptimization_handler_ = 90e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); 91a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org} 92a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 93a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 9457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid LoadFieldStub::InitializeInterfaceDescriptor( 9557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org Isolate* isolate, 9657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org CodeStubInterfaceDescriptor* descriptor) { 9757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org static Register registers[] = { r0 }; 9857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->register_param_count_ = 1; 9957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->register_params_ = registers; 10057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->deoptimization_handler_ = NULL; 10157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org} 10257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 10357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 10457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.orgvoid KeyedLoadFieldStub::InitializeInterfaceDescriptor( 10557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org Isolate* isolate, 10657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org CodeStubInterfaceDescriptor* descriptor) { 10757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org static Register registers[] = { r1 }; 10857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->register_param_count_ = 1; 10957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->register_params_ = registers; 11057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->deoptimization_handler_ = NULL; 11157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org} 11257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 11357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 1147bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.orgvoid KeyedStoreFastElementStub::InitializeInterfaceDescriptor( 1157bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org Isolate* isolate, 1167bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org CodeStubInterfaceDescriptor* descriptor) { 1177bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org static Register registers[] = { r2, r1, r0 }; 1187bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org descriptor->register_param_count_ = 3; 1197bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org descriptor->register_params_ = registers; 1207bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org descriptor->deoptimization_handler_ = 1217bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); 1227bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org} 1237bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org 1247bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org 12594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.orgvoid TransitionElementsKindStub::InitializeInterfaceDescriptor( 12694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org Isolate* isolate, 12794b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org CodeStubInterfaceDescriptor* descriptor) { 12894b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org static Register registers[] = { r0, r1 }; 12994b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org descriptor->register_param_count_ = 2; 13094b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org descriptor->register_params_ = registers; 13194b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org Address entry = 13294b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; 13394b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org descriptor->deoptimization_handler_ = FUNCTION_ADDR(entry); 13494b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org} 13594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org 13694b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org 137ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid CompareNilICStub::InitializeInterfaceDescriptor( 138ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org Isolate* isolate, 1394a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org CodeStubInterfaceDescriptor* descriptor) { 140ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org static Register registers[] = { r0 }; 141ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org descriptor->register_param_count_ = 1; 142ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org descriptor->register_params_ = registers; 143ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org descriptor->deoptimization_handler_ = 144ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org FUNCTION_ADDR(CompareNilIC_Miss); 145a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org descriptor->SetMissHandler( 146a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate)); 147ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org} 148ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 149ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 150ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void InitializeArrayConstructorDescriptor( 151ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org Isolate* isolate, 152ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org CodeStubInterfaceDescriptor* descriptor, 153ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org int constant_stack_parameter_count) { 1544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // register state 155ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // r0 -- number of arguments 15657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org // r1 -- function 1574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // r2 -- type info cell with elements kind 15857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org static Register registers[] = { r1, r2 }; 15957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org descriptor->register_param_count_ = 2; 160ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org if (constant_stack_parameter_count != 0) { 161ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // stack param count needs (constructor pointer, and single argument) 162ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org descriptor->stack_parameter_count_ = &r0; 163ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } 164ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; 1654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org descriptor->register_params_ = registers; 166f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; 1674a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org descriptor->deoptimization_handler_ = 168dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org Runtime::FunctionForId(Runtime::kArrayConstructor)->entry; 1694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org} 1704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 1714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 172d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgstatic void InitializeInternalArrayConstructorDescriptor( 173d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Isolate* isolate, 174d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org CodeStubInterfaceDescriptor* descriptor, 175d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org int constant_stack_parameter_count) { 176d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // register state 177d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // r0 -- number of arguments 178d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // r1 -- constructor function 179d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org static Register registers[] = { r1 }; 180d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org descriptor->register_param_count_ = 1; 181d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 182d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org if (constant_stack_parameter_count != 0) { 183d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // stack param count needs (constructor pointer, and single argument) 184d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org descriptor->stack_parameter_count_ = &r0; 185d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 186d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; 187d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org descriptor->register_params_ = registers; 188d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; 189d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org descriptor->deoptimization_handler_ = 190dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry; 191d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 192d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 193d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 1944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( 1954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Isolate* isolate, 1964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org CodeStubInterfaceDescriptor* descriptor) { 197ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org InitializeArrayConstructorDescriptor(isolate, descriptor, 0); 1984a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org} 1994a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 2004a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 2014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( 2024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Isolate* isolate, 2034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org CodeStubInterfaceDescriptor* descriptor) { 204ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org InitializeArrayConstructorDescriptor(isolate, descriptor, 1); 2054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org} 2064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 2074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 2084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( 2094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Isolate* isolate, 2104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org CodeStubInterfaceDescriptor* descriptor) { 211ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org InitializeArrayConstructorDescriptor(isolate, descriptor, -1); 2124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org} 2134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 2144a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 215b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.orgvoid ToBooleanStub::InitializeInterfaceDescriptor( 216b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org Isolate* isolate, 217b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org CodeStubInterfaceDescriptor* descriptor) { 218b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org static Register registers[] = { r0 }; 219b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org descriptor->register_param_count_ = 1; 220b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org descriptor->register_params_ = registers; 221b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org descriptor->deoptimization_handler_ = 222b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org FUNCTION_ADDR(ToBooleanIC_Miss); 223b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org descriptor->SetMissHandler( 224b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); 225b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org} 226b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org 227b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org 228d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( 229d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Isolate* isolate, 230d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org CodeStubInterfaceDescriptor* descriptor) { 231d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 0); 232d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 233d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 234d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 235d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( 236d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Isolate* isolate, 237d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org CodeStubInterfaceDescriptor* descriptor) { 238d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InitializeInternalArrayConstructorDescriptor(isolate, descriptor, 1); 239d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 240d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 241d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 242d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( 243d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Isolate* isolate, 244d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org CodeStubInterfaceDescriptor* descriptor) { 245d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1); 246d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 247d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 248d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 249e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.orgvoid StoreGlobalStub::InitializeInterfaceDescriptor( 250e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org Isolate* isolate, 251e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org CodeStubInterfaceDescriptor* descriptor) { 252e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org static Register registers[] = { r1, r2, r0 }; 253e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org descriptor->register_param_count_ = 3; 254e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org descriptor->register_params_ = registers; 255e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org descriptor->deoptimization_handler_ = 256e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org FUNCTION_ADDR(StoreIC_MissFromStubFailure); 257e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org} 258e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 259e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 260ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.orgvoid ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor( 261ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Isolate* isolate, 262ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org CodeStubInterfaceDescriptor* descriptor) { 263ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org static Register registers[] = { r0, r3, r1, r2 }; 264ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org descriptor->register_param_count_ = 4; 265ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org descriptor->register_params_ = registers; 266ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org descriptor->deoptimization_handler_ = 267ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); 268ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org} 269ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 270ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 27165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#define __ ACCESS_MASM(masm) 27265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 273e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 27465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, 27565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* slow, 276fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Condition cond); 27765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, 27865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register lhs, 27965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register rhs, 28065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* lhs_not_nan, 28165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* slow, 28265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org bool strict); 28365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 28465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register lhs, 28565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register rhs); 28665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 28765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 28877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { 28977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org // Update the static counter each time a new code stub is generated. 29077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org Isolate* isolate = masm->isolate(); 29177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org isolate->counters()->code_stubs()->Increment(); 29277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org 29377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); 29477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org int param_count = descriptor->register_param_count_; 29577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org { 29677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org // Call the runtime system in a fresh internal frame. 29777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 29877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org ASSERT(descriptor->register_param_count_ == 0 || 29977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org r0.is(descriptor->register_params_[param_count - 1])); 30077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org // Push arguments 30177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org for (int i = 0; i < param_count; ++i) { 30277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org __ push(descriptor->register_params_[i]); 30377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org } 304a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org ExternalReference miss = descriptor->miss_handler(); 30577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org __ CallExternalReference(miss, descriptor->register_param_count_); 30677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org } 30777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org 30877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org __ Ret(); 30977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org} 31077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org 31177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org 31265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FastNewClosureStub::Generate(MacroAssembler* masm) { 31365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Create a new closure from the given function info in new 31465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // space. Set the context to the current context in cp. 3155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org Counters* counters = masm->isolate()->counters(); 3165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 31765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label gc; 31865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 31965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Pop the function info from the stack. 32065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ pop(r3); 32165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 32265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Attempt to allocate new JSFunction in new space. 3232bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT); 32465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r7); 3265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 327e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org int map_index = Context::FunctionMapIndex(language_mode_, is_generator_); 328ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 32946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Compute the function map in the current native context and set that 33065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // as the map of the allocated object. 33146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 33246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset)); 3335a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ ldr(r5, MemOperand(r2, Context::SlotOffset(map_index))); 3345a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ str(r5, FieldMemOperand(r0, HeapObject::kMapOffset)); 33565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 33665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Initialize the rest of the function. We don't have to update the 33765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // write barrier because the allocated object is in new space. 33865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex); 3395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); 34065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 34165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, FieldMemOperand(r0, JSObject::kElementsOffset)); 3425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ str(r5, FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset)); 34365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 34465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset)); 34565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 346a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 34765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Initialize the code pointer in the function to be the one 34865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // found in the shared function info object. 3495a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // But first check if there is an optimized version for our context. 3505a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org Label check_optimized; 3515a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org Label install_unoptimized; 3525a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org if (FLAG_cache_optimized_code) { 3535a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ ldr(r1, 3545a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org FieldMemOperand(r3, SharedFunctionInfo::kOptimizedCodeMapOffset)); 3555a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ tst(r1, r1); 3565a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ b(ne, &check_optimized); 3575a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org } 3585a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ bind(&install_unoptimized); 3595a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); 3605a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset)); 36165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset)); 36265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 36365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); 36465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 36565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Return result. The argument function info has been popped already. 36665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 36765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3685a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ bind(&check_optimized); 3695a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 3705a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1, r6, r7); 3715a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 37246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // r2 holds native context, r1 points to fixed array of 3-element entries 37346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // (native context, optimized code, literals). 3745a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // The optimized code map must never be empty, so check the first elements. 3755a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org Label install_optimized; 3765a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Speculatively move code object into r4. 3774e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ ldr(r4, FieldMemOperand(r1, SharedFunctionInfo::kFirstCodeSlot)); 3784e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ ldr(r5, FieldMemOperand(r1, SharedFunctionInfo::kFirstContextSlot)); 3795a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ cmp(r2, r5); 3805a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ b(eq, &install_optimized); 3815a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 3825a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Iterate through the rest of map backwards. r4 holds an index as a Smi. 3835a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org Label loop; 3845a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ ldr(r4, FieldMemOperand(r1, FixedArray::kLengthOffset)); 3855a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ bind(&loop); 3865a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Do not double check first entry. 3874e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ cmp(r4, Operand(Smi::FromInt(SharedFunctionInfo::kSecondEntryIndex))); 3885a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ b(eq, &install_unoptimized); 3894e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ sub(r4, r4, Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength))); 3905a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 391bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4)); 3925a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ ldr(r5, MemOperand(r5)); 3935a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ cmp(r2, r5); 3945a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ b(ne, &loop); 3955a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Hit: fetch the optimized code. 3965a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ add(r5, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 397bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r5, r5, Operand::PointerOffsetFromSmiKey(r4)); 3985a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ add(r5, r5, Operand(kPointerSize)); 3995a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ ldr(r4, MemOperand(r5)); 4005a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 4015a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ bind(&install_optimized); 4025a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ IncrementCounter(counters->fast_new_closure_install_optimized(), 4035a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 1, r6, r7); 4045a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 4055a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // TODO(fschneider): Idea: store proper code pointers in the map and either 4065a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // unmangle them on marking or do nothing as the whole map is discarded on 4075a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // major GC anyway. 4085a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); 4095a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ str(r4, FieldMemOperand(r0, JSFunction::kCodeEntryOffset)); 4105a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 4115a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Now link a function into a list of optimized functions. 4125a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ ldr(r4, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST)); 4135a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 4145a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ str(r4, FieldMemOperand(r0, JSFunction::kNextFunctionLinkOffset)); 4155a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // No need for write barrier as JSFunction (eax) is in the new space. 4165a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 4175a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ str(r0, ContextOperand(r2, Context::OPTIMIZED_FUNCTIONS_LIST)); 4185a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Store JSFunction (eax) into edx before issuing write barrier as 4195a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // it clobbers all the registers passed. 4205a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ mov(r4, r0); 4215a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ RecordWriteContextSlot( 4225a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org r2, 4235a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST), 4245a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org r4, 4255a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org r1, 4265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org kLRHasNotBeenSaved, 4275a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org kDontSaveFPRegs); 4285a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 4295a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // Return result. The argument function info has been popped already. 4305a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org __ Ret(); 4315a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org 43265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Create a new closure through the slower runtime call. 43365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&gc); 43421b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org __ LoadRoot(r4, Heap::kFalseValueRootIndex); 43521b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org __ Push(cp, r3, r4); 43621b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org __ TailCallRuntime(Runtime::kNewClosure, 3, 1); 43765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 43865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 43965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 44065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FastNewContextStub::Generate(MacroAssembler* masm) { 44165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Try to allocate the context in new space. 44265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label gc; 4430ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org int length = slots_ + Context::MIN_CONTEXT_SLOTS; 44465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 44565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Attempt to allocate the context in new space. 4462bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT); 44765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 44865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Load the function from the stack. 44965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, MemOperand(sp, 0)); 45065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 451f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up the object header. 452fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ LoadRoot(r1, Heap::kFunctionContextMapRootIndex); 4530ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org __ mov(r2, Operand(Smi::FromInt(length))); 45465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); 455fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 45665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 457fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Set up the fixed slots, copy the global object from the previous context. 45846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 45965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r1, Operand(Smi::FromInt(0))); 46065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); 4616d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX))); 46265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, MemOperand(r0, Context::SlotOffset(Context::EXTENSION_INDEX))); 46346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ str(r2, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 46465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 46565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Initialize the rest of the slots to undefined. 46665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 4670ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 46865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, MemOperand(r0, Context::SlotOffset(i))); 46965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 47065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 47165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Remove the on-stack argument and return. 47265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(cp, r0); 47365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ pop(); 47465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 47565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 47665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Need to collect. Call into runtime system. 47765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&gc); 4786d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1); 47965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 48065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 48165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 482a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.orgvoid FastNewBlockContextStub::Generate(MacroAssembler* masm) { 483a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Stack layout on entry: 484a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // 485a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // [sp]: function. 486a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // [sp + kPointerSize]: serialized scope info 487a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 488a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Try to allocate the context in new space. 489a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org Label gc; 490a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org int length = slots_ + Context::MIN_CONTEXT_SLOTS; 4912bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT); 492a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 493a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Load the function from the stack. 494a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ ldr(r3, MemOperand(sp, 0)); 495a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 496a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Load the serialized scope info from the stack. 497a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 498a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 499f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up the object header. 500a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ LoadRoot(r2, Heap::kBlockContextMapRootIndex); 501a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 502a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ mov(r2, Operand(Smi::FromInt(length))); 503a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); 504a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 50546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // If this block context is nested in the native context we get a smi 506a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // sentinel instead of a function. The block context should get the 50746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // canonical empty function of the native context as its closure which 508a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // we still have to look up. 509a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org Label after_sentinel; 510a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ JumpIfNotSmi(r3, &after_sentinel); 511a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org if (FLAG_debug_code) { 512a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ cmp(r3, Operand::Zero()); 513594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kExpected0AsASmiSentinel); 514a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org } 515a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ ldr(r3, GlobalObjectOperand()); 51646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset)); 517a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ ldr(r3, ContextOperand(r3, Context::CLOSURE_INDEX)); 518a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ bind(&after_sentinel); 519a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 520fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Set up the fixed slots, copy the global object from the previous context. 52146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 522a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ str(r3, ContextOperand(r0, Context::CLOSURE_INDEX)); 523a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ str(cp, ContextOperand(r0, Context::PREVIOUS_INDEX)); 524a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ str(r1, ContextOperand(r0, Context::EXTENSION_INDEX)); 52546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ str(r2, ContextOperand(r0, Context::GLOBAL_OBJECT_INDEX)); 526a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 527a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Initialize the rest of the slots to the hole value. 528a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); 529a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org for (int i = 0; i < slots_; i++) { 530a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ str(r1, ContextOperand(r0, i + Context::MIN_CONTEXT_SLOTS)); 531a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org } 532a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 533a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Remove the on-stack argument and return. 534a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ mov(cp, r0); 535a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 536a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ Ret(); 537a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 538a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org // Need to collect. Call into runtime system. 539a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ bind(&gc); 540a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1); 541a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org} 542a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 543a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org 54465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Takes a Smi and converts to an IEEE 64 bit floating point value in two 54565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and 54665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// 52 fraction bits (20 in the first word, 32 in the second). Zeros is a 54765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// scratch register. Destroys the source register. No GC occurs during this 54865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// stub so you don't have to set up the frame. 549a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass ConvertToDoubleStub : public PlatformCodeStub { 55065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org public: 55165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ConvertToDoubleStub(Register result_reg_1, 55265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register result_reg_2, 55365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register source_reg, 55465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch_reg) 55565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org : result1_(result_reg_1), 55665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org result2_(result_reg_2), 55765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org source_(source_reg), 55865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org zeros_(scratch_reg) { } 55965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 56065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org private: 56165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register result1_; 56265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register result2_; 56365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register source_; 56465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register zeros_; 56565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 56665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Minor key encoding in 16 bits. 56765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org class ModeBits: public BitField<OverwriteMode, 0, 2> {}; 56865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org class OpBits: public BitField<Token::Value, 2, 14> {}; 56965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 57065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Major MajorKey() { return ConvertToDouble; } 57165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int MinorKey() { 57265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Encode the parameters in a unique 16 bit value. 57365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org return result1_.code() + 57465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (result2_.code() << 4) + 57565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (source_.code() << 8) + 57665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (zeros_.code() << 12); 57765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 57865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 57965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org void Generate(MacroAssembler* masm); 58065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}; 58165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 58265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 58365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid ConvertToDoubleStub::Generate(MacroAssembler* masm) { 584160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Register exponent = result1_; 585160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Register mantissa = result2_; 58644bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org 58765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label not_special; 588bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(source_); 58965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Move sign bit from source to destination. This works because the sign bit 59065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // in the exponent word of the double has the same position and polarity as 59165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // the 2's complement sign bit in a Smi. 59265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); 59365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); 59465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Subtract from 0 if source was negative. 59559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ rsb(source_, source_, Operand::Zero(), LeaveCC, ne); 59665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 59765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // We have -1, 0 or 1, which we treat specially. Register source_ contains 59865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // absolute value: it is either equal to 1 (special case of -1 and 1), 59965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // greater than 1 (not a special case) or less than 1 (special case of 0). 60065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(source_, Operand(1)); 60165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(gt, ¬_special); 60265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 60365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // For 1 or -1 we need to or in the 0 exponent (biased to 1023). 6041456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const uint32_t exponent_word_for_1 = 60565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org HeapNumber::kExponentBias << HeapNumber::kExponentShift; 60665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq); 60765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // 1, 0 and -1 all have 0 for the second word. 60859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(mantissa, Operand::Zero()); 60965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 61065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 61165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(¬_special); 612b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org __ clz(zeros_, source_); 61365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Compute exponent and or it into the exponent register. 61465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // We use mantissa as a scratch register here. Use a fudge factor to 61565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts 61665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // that fit in the ARM's constant field. 61765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int fudge = 0x400; 61865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias - fudge)); 61965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(mantissa, mantissa, Operand(fudge)); 62065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(exponent, 62165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org exponent, 62265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Operand(mantissa, LSL, HeapNumber::kExponentShift)); 62365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Shift up the source chopping the top bit off. 62465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(zeros_, zeros_, Operand(1)); 62565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. 62665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(source_, Operand(source_, LSL, zeros_)); 62765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Compute lower part of fraction (last 12 bits). 62865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); 62965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // And the top (top 20 bits). 63065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(exponent, 63165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org exponent, 63265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); 63365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 63465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 63565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 63665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool WriteInt32ToHeapNumberStub::IsPregenerated() { 638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // These variants are compiled ahead of time. See next method. 639c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) { 640c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com return true; 641c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 642c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (the_int_.is(r2) && the_heap_number_.is(r0) && scratch_.is(r3)) { 643c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com return true; 644c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 645c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Other register combinations are generated as and when they are needed, 646c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // so it is unsafe to call them from stubs (we can't generate a stub while 647c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // we are generating a stub). 648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com return false; 649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6528432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( 6538432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org Isolate* isolate) { 654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com WriteInt32ToHeapNumberStub stub1(r1, r0, r2); 655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com WriteInt32ToHeapNumberStub stub2(r2, r0, r3); 6568432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org stub1.GetCode(isolate)->set_is_pregenerated(true); 6578432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org stub2.GetCode(isolate)->set_is_pregenerated(true); 658c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 659c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 660c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 66165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment for class. 66265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { 66365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label max_negative_int; 66465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // the_int_ has the answer which is a signed int32 but not a Smi. 66565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // We test for the special value that has a different exponent. This test 66665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // has the neat side effect of setting the flags according to the sign. 66765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); 66865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(the_int_, Operand(0x80000000u)); 66965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &max_negative_int); 67065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Set up the correct exponent in scratch_. All non-Smi int32s have the same. 67165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). 67265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org uint32_t non_smi_exponent = 67365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; 67465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch_, Operand(non_smi_exponent)); 67565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Set the sign bit in scratch_ if the value was negative. 67665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs); 67765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Subtract from 0 if the value was negative. 67859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ rsb(the_int_, the_int_, Operand::Zero(), LeaveCC, cs); 67965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // We should be masking the implict first digit of the mantissa away here, 68065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // but it just ends up combining harmlessly with the last digit of the 68165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get 68265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // the most significant 1 to hit the last bit of the 12 bit sign and exponent. 68365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); 68465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; 68565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance)); 68665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(scratch_, FieldMemOperand(the_heap_number_, 68765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org HeapNumber::kExponentOffset)); 68865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance)); 68965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(scratch_, FieldMemOperand(the_heap_number_, 69065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org HeapNumber::kMantissaOffset)); 69165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 69265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 69365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&max_negative_int); 69465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // The max negative int32 is stored as a positive number in the mantissa of 69565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // a double because it uses a sign bit instead of using two's complement. 69665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // The actual mantissa bits stored are all 0 because the implicit most 69765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // significant 1 bit is not stored. 69865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org non_smi_exponent += 1 << HeapNumber::kExponentShift; 69965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); 70065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); 70159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(ip, Operand::Zero()); 70265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); 70365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 70465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 70565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 70665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 70765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Handle the case where the lhs and rhs are the same object. 70865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// Equality is almost reflexive (everything but NaN), so this is a test 70965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// for "identity and not NaN". 71065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, 71165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* slow, 712fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Condition cond) { 71365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label not_identical; 71465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label heap_number, return_equal; 71565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r0, r1); 71665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, ¬_identical); 71765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 718d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 719fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // so we do the second best thing - test it ourselves. 720fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // They are both equal and they are not both Smis so both of them are not 721fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Smis. If it's not a heap number, then return equal. 722fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond == lt || cond == gt) { 723fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ CompareObjectType(r0, r4, r4, FIRST_SPEC_OBJECT_TYPE); 724fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ b(ge, slow); 725fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } else { 726fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); 727fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ b(eq, &heap_number); 728fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Comparing JS objects with <=, >= is complicated. 729fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond != eq) { 730fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ cmp(r4, Operand(FIRST_SPEC_OBJECT_TYPE)); 73165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ge, slow); 732fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Normally here we fall through to return_equal, but undefined is 733fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // special: (undefined == undefined) == true, but 734fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // (undefined <= undefined) == false! See ECMAScript 11.8.5. 735fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond == le || cond == ge) { 736fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ cmp(r4, Operand(ODDBALL_TYPE)); 737fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ b(ne, &return_equal); 738fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 739fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ cmp(r0, r2); 740fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ b(ne, &return_equal); 741fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond == le) { 742fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // undefined <= undefined should fail. 743fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ mov(r0, Operand(GREATER)); 744fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } else { 745fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // undefined >= undefined should fail. 746fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ mov(r0, Operand(LESS)); 74765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 748fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Ret(); 74965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 75065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 75165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 75265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 75365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&return_equal); 754378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org if (cond == lt) { 75565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(GREATER)); // Things aren't less than themselves. 756378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } else if (cond == gt) { 75765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(LESS)); // Things aren't greater than themselves. 75865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 75965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. 76065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 76165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 76265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 763fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // For less and greater we don't have to check for NaN since the result of 764fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // x < x is false regardless. For the others here is some code to check 765fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // for NaN. 766fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond != lt && cond != gt) { 767fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ bind(&heap_number); 768fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // It is a heap number, so return non-equal if it's NaN and equal if it's 769fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // not NaN. 770fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 771fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // The representation of NaN values has all exponent bits (52..62) set, 772fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // and not all mantissa bits (0..51) clear. 773fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Read top bits of double representation (second word of value). 774fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 775fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Test that exponent bits are all set. 776fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits); 777fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // NaNs have all-one exponents so they sign extend to -1. 778fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ cmp(r3, Operand(-1)); 779fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ b(ne, &return_equal); 780fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 781fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Shift out flag and all exponent bits, retaining only mantissa. 782fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord)); 783fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // Or with all low-bits of mantissa. 784fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 785fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ orr(r0, r3, Operand(r2), SetCC); 786fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // For equal we already have the right value in r0: Return zero (equal) 787fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // if all bits in mantissa are zero (it's an Infinity) and non-zero if 788fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // not (it's a NaN). For <= and >= we need to load r0 with the failing 789fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // value if it's a NaN. 790fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond != eq) { 791fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // All-zero means Infinity means equal. 792fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Ret(eq); 793fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cond == le) { 794fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail. 795fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } else { 796fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ mov(r0, Operand(LESS)); // NaN >= NaN should fail. 79765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 79865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 799fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Ret(); 80065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 801fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // No fall through here. 80265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 80365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(¬_identical); 80465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 80565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 80665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 80765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment at call site. 80865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, 80965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register lhs, 81065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register rhs, 81165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* lhs_not_nan, 81265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* slow, 81365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org bool strict) { 81465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT((lhs.is(r0) && rhs.is(r1)) || 81565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (lhs.is(r1) && rhs.is(r0))); 81665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 81765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label rhs_is_smi; 8187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(rhs, &rhs_is_smi); 81965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 82065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Lhs is a Smi. Check whether the rhs is a heap number. 82165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE); 82265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (strict) { 82365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If rhs is not a number and lhs is a Smi then strict equality cannot 82465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // succeed. Return non-equal 82565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If rhs is r0 then there is already a non zero value in it. 82665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (!rhs.is(r0)) { 82765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); 82865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 82965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(ne); 83065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 83165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Smi compared non-strictly with a non-Smi non-heap-number. Call 83265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // the runtime. 83365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, slow); 83465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 83565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 83665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Lhs is a smi, rhs is a number. 837e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Convert lhs to a double in d7. 838bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d7, lhs); 839e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Load the double from rhs, tagged HeapNumber r0, to d6. 840e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r7, rhs, Operand(kHeapObjectTag)); 841e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d6, r7, HeapNumber::kValueOffset); 84265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 84365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // We now have both loaded as doubles but we can skip the lhs nan check 84465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // since it's a smi. 84565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(lhs_not_nan); 84665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 84765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&rhs_is_smi); 84865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Rhs is a smi. Check whether the non-smi lhs is a heap number. 84965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE); 85065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (strict) { 85165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If lhs is not a number and rhs is a smi then strict equality cannot 85265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // succeed. Return non-equal. 85365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If lhs is r0 then there is already a non zero value in it. 85465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (!lhs.is(r0)) { 85565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); 85665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 85765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(ne); 85865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 85965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Smi compared non-strictly with a non-smi non-heap-number. Call 86065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // the runtime. 86165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, slow); 86265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 86365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 86465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Rhs is a smi, lhs is a heap number. 865e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Load the double from lhs, tagged HeapNumber r1, to d7. 866e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r7, lhs, Operand(kHeapObjectTag)); 867e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d7, r7, HeapNumber::kValueOffset); 868e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Convert rhs to a double in d6 . 869bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d6, rhs); 87065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Fall through to both_loaded_as_doubles. 87165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 87265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 87365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 87465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment at call site. 87565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 87665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register lhs, 87765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register rhs) { 87865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT((lhs.is(r0) && rhs.is(r1)) || 87965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (lhs.is(r1) && rhs.is(r0))); 88065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 881d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org // If either operand is a JS object or an oddball value, then they are 88265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // not equal since their pointers are different. 88365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // There is no test for undetectability in strict equality. 884c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 88565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label first_non_object; 88665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the type of the first operand into r2 and compare it with 887d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org // FIRST_SPEC_OBJECT_TYPE. 888d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ CompareObjectType(rhs, r2, r2, FIRST_SPEC_OBJECT_TYPE); 88965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(lt, &first_non_object); 89065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 89165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Return non-zero (r0 is not zero) 89265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label return_not_equal; 89365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&return_not_equal); 89465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 89565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 89665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&first_non_object); 89765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check for oddballs: true, false, null, undefined. 89865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r2, Operand(ODDBALL_TYPE)); 89965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &return_not_equal); 90065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 901d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE); 90265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ge, &return_not_equal); 90365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 90465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check for oddballs: true, false, null, undefined. 90565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r3, Operand(ODDBALL_TYPE)); 90665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &return_not_equal); 90765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 9084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Now that we have the types we might as well check for 9094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // internalized-internalized. 910ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 911ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ orr(r2, r2, Operand(r3)); 912ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ tst(r2, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 913ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ b(eq, &return_not_equal); 91465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 91565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 91665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 91765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// See comment at call site. 91865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 91965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register lhs, 92065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register rhs, 92165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* both_loaded_as_doubles, 92265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* not_heap_numbers, 92365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* slow) { 92465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT((lhs.is(r0) && rhs.is(r1)) || 92565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (lhs.is(r1) && rhs.is(r0))); 92665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 92765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); 92865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, not_heap_numbers); 92965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); 93065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r2, r3); 93165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. 93265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 93365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Both are heap numbers. Load them up then jump to the code we have 93465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // for that. 935e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r7, rhs, Operand(kHeapObjectTag)); 936e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d6, r7, HeapNumber::kValueOffset); 937e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r7, lhs, Operand(kHeapObjectTag)); 938e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d7, r7, HeapNumber::kValueOffset); 93965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(both_loaded_as_doubles); 94065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 94165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 94265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 9434a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org// Fast negative check for internalized-to-internalized equality. 9444a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgstatic void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 9454a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register lhs, 9464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register rhs, 9474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Label* possible_strings, 9484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Label* not_both_strings) { 94965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT((lhs.is(r0) && rhs.is(r1)) || 95065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org (lhs.is(r1) && rhs.is(r0))); 95165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 95265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2 is object type of rhs. 95365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label object_test; 954ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 95565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r2, Operand(kIsNotStringMask)); 95665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &object_test); 957ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ tst(r2, Operand(kIsNotInternalizedMask)); 958ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ b(ne, possible_strings); 95965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE); 96065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ge, not_both_strings); 961ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ tst(r3, Operand(kIsNotInternalizedMask)); 962ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ b(ne, possible_strings); 96365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 9644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Both are internalized. We already checked they weren't the same pointer 96565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // so they are not equal. 96665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(NOT_EQUAL)); 96765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 96865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 96965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&object_test); 970d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE)); 97165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(lt, not_both_strings); 972d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE); 97365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(lt, not_both_strings); 97465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If both objects are undetectable, they are equal. Otherwise, they 97565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // are not equal, since they are different objects and an object is not 97665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // equal to undefined. 97765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); 97865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); 97965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); 98065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(r0, r2, Operand(r3)); 98165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); 98265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); 98365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 98465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 98565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 98665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 98765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, 98865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register object, 98965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register result, 99065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch1, 99165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch2, 99265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch3, 99365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* not_found) { 99465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Use of registers. Register result is used as a temporary. 99565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register number_string_cache = result; 99665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register mask = scratch3; 99765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 99865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Load the number string cache. 99965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); 100065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 100165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Make the hash mask from the length of the number string cache. It 100265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // contains two elements (number and string) for each cache entry. 100365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); 100465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Divide length by two (length is a smi). 100565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); 100665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(mask, mask, Operand(1)); // Make mask. 100765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 100865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Calculate the entry in the number string cache. The hash value in the 100965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // number string cache for smis is just the smi value, and the hash for 101065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // doubles is the xor of the upper and lower words. See 101165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Heap::GetNumberStringCache. 10127979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Isolate* isolate = masm->isolate(); 101365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label is_smi; 101465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label load_result_from_cache; 1015ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ JumpIfSmi(object, &is_smi); 1016ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ CheckMap(object, 1017ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org scratch1, 1018ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Heap::kHeapNumberMapRootIndex, 1019ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org not_found, 1020ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org DONT_DO_SMI_CHECK); 1021e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 1022ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org STATIC_ASSERT(8 == kDoubleSize); 1023ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ add(scratch1, 1024ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org object, 1025ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Operand(HeapNumber::kValueOffset - kHeapObjectTag)); 1026ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); 1027ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ eor(scratch1, scratch1, Operand(scratch2)); 1028ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ and_(scratch1, scratch1, Operand(mask)); 1029ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1030ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Calculate address of entry in string cache: each entry consists 1031ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // of two pointer sized fields. 1032ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ add(scratch1, 1033ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org number_string_cache, 1034ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Operand(scratch1, LSL, kPointerSizeLog2 + 1)); 1035ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org 1036ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org Register probe = mask; 1037ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ ldr(probe, 1038ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org FieldMemOperand(scratch1, FixedArray::kHeaderSize)); 1039ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ JumpIfSmi(probe, not_found); 1040ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ sub(scratch2, object, Operand(kHeapObjectTag)); 1041ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ vldr(d0, scratch2, HeapNumber::kValueOffset); 1042ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ sub(probe, probe, Operand(kHeapObjectTag)); 1043ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ vldr(d1, probe, HeapNumber::kValueOffset); 1044ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ VFPCompareAndSetFlags(d0, d1); 1045ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ b(ne, not_found); // The cache did not contain this value. 1046ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ b(&load_result_from_cache); 104765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 104865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&is_smi); 104965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch = scratch1; 105065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(scratch, mask, Operand(object, ASR, 1)); 105165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Calculate address of entry in string cache: each entry consists 105265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // of two pointer sized fields. 105365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(scratch, 105465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org number_string_cache, 105565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Operand(scratch, LSL, kPointerSizeLog2 + 1)); 105665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 105765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check if the entry is the smi we are looking for. 105865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 105965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(object, probe); 106065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, not_found); 106165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 106265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the result from the cache. 106365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&load_result_from_cache); 106465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(result, 106565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); 10667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(isolate->counters()->number_to_string_native(), 106765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1, 106865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org scratch1, 106965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org scratch2); 107065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 107165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 107265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 107365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid NumberToStringStub::Generate(MacroAssembler* masm) { 107465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label runtime; 107565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 107665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, MemOperand(sp, 0)); 107765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 107865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Generate code to lookup number in the number string cache. 1079ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, &runtime); 108065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(1 * kPointerSize)); 108165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 108265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 108365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&runtime); 108465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Handle number to string in the runtime system if not found in the cache. 108565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); 108665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 108765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 108865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1089fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgstatic void ICCompareStub_CheckInputType(MacroAssembler* masm, 1090fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register input, 1091fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register scratch, 1092fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org CompareIC::State expected, 1093fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label* fail) { 1094fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label ok; 1095fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (expected == CompareIC::SMI) { 1096fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(input, fail); 10978432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org } else if (expected == CompareIC::NUMBER) { 1098fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfSmi(input, &ok); 1099fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 1100fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org DONT_DO_SMI_CHECK); 1101fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 11024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // We could be strict about internalized/non-internalized here, but as long as 1103fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // hydrogen doesn't care, the stub doesn't have to care either. 1104fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ bind(&ok); 1105fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org} 1106fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1107fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1108fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org// On entry r1 and r2 are the values to be compared. 110965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// On exit r0 is 0, positive or negative to indicate the result of 111065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// the comparison. 1111fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid ICCompareStub::GenerateGeneric(MacroAssembler* masm) { 1112fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register lhs = r1; 1113fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register rhs = r0; 1114fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Condition cc = GetCondition(); 1115fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1116fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label miss; 1117fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ICCompareStub_CheckInputType(masm, lhs, r2, left_, &miss); 1118fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ICCompareStub_CheckInputType(masm, rhs, r3, right_, &miss); 111965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 112065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label slow; // Call builtin. 112165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label not_smis, both_loaded_as_doubles, lhs_not_nan; 112265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1123fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label not_two_smis, smi_done; 1124fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ orr(r2, r1, r0); 1125fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(r2, ¬_two_smis); 1126fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ mov(r1, Operand(r1, ASR, 1)); 1127fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ sub(r0, r1, Operand(r0, ASR, 1)); 1128fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Ret(); 1129fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ bind(¬_two_smis); 1130d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com 113165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // NOTICE! This code is only reached after a smi-fast-case check, so 113265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // it is certain that at least one operand isn't a smi. 113365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 113465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Handle the case where the objects are identical. Either returns the answer 113565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // or goes to slow. Only falls through if the objects were not identical. 1136fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org EmitIdenticalObjectComparison(masm, &slow, cc); 113765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 113865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If either is a Smi (we know that not both are), then they can only 113965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // be strictly equal if the other is a HeapNumber. 114065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 114165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT_EQ(0, Smi::FromInt(0)); 1142fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ and_(r2, lhs, Operand(rhs)); 11437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfNotSmi(r2, ¬_smis); 114465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 114565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // 1) Return the answer. 114665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // 2) Go to slow. 114765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // 3) Fall through to both_loaded_as_doubles. 114865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // 4) Jump to lhs_not_nan. 114965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // In cases 3 and 4 we have found out we were dealing with a number-number 115065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // comparison. If VFP3 is supported the double values of the numbers have 115165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // been loaded into d7 and d6. Otherwise, the double values have been loaded 115265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // into r0, r1, r2, and r3. 1153fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); 115465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 115565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&both_loaded_as_doubles); 115665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // The arguments have been converted to doubles and stored in d6 and d7, if 115765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // VFP3 is supported, or in r0, r1, r2, and r3. 11587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Isolate* isolate = masm->isolate(); 1159e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&lhs_not_nan); 1160e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Label no_nan; 1161e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // ARMv7 VFP3 instructions to implement double precision comparison. 1162e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ VFPCompareAndSetFlags(d7, d6); 1163e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Label nan; 1164e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(vs, &nan); 1165e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(EQUAL), LeaveCC, eq); 1166e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(LESS), LeaveCC, lt); 1167e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(GREATER), LeaveCC, gt); 1168e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ Ret(); 116965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1170e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&nan); 1171e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // If one of the sides was a NaN then the v flag is set. Load r0 with 1172e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // whatever it takes to make the comparison fail, since comparisons with NaN 1173e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // always fail. 1174e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (cc == lt || cc == le) { 1175e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(GREATER)); 117665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 1177e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(LESS)); 117865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 1179e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ Ret(); 118065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 118165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(¬_smis); 118265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // At this point we know we are dealing with two different objects, 118365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // and neither of them is a Smi. The objects are in rhs_ and lhs_. 1184fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (strict()) { 118565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // This returns non-equal for some object types, or falls through if it 118665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // was not lucky. 1187fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); 118865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 118965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 11904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Label check_for_internalized_strings; 119165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label flat_string_check; 119265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check for heap-number-heap-number comparison. Can jump to slow case, 119365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // or load both doubles into r0, r1, r2, r3 and jump to the code that handles 11944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // that case. If the inputs are not doubles then jumps to 11954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // check_for_internalized_strings. 119665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // In this case r2 will contain the type of rhs_. Never falls through. 119765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org EmitCheckForTwoHeapNumbers(masm, 1198fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org lhs, 1199fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org rhs, 120065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &both_loaded_as_doubles, 12014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org &check_for_internalized_strings, 120265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &flat_string_check); 120365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 12044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&check_for_internalized_strings); 120565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 12064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // internalized strings. 1207fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cc == eq && !strict()) { 12084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Returns an answer for two internalized strings or two detectable objects. 120965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Otherwise jumps to string case or not both strings case. 121065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Assumes that r2 is the type of rhs_ on entry. 12114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org EmitCheckForInternalizedStringsOrObjects( 12124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org masm, lhs, rhs, &flat_string_check, &slow); 121365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 121465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 121565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check for both being sequential ASCII strings, and inline if that is the 121665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // case. 121765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&flat_string_check); 121865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1219fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, r2, r3, &slow); 122065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 12217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3); 1222fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cc == eq) { 12231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org StringCompareStub::GenerateFlatAsciiStringEquals(masm, 1224fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org lhs, 1225fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org rhs, 122665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org r2, 122765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org r3, 12281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org r4); 12291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } else { 12301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 1231fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org lhs, 1232fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org rhs, 12331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org r2, 12341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org r3, 12351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org r4, 12361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org r5); 12371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 123865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Never falls through to here. 123965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 124065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&slow); 124165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1242fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Push(lhs, rhs); 124365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Figure out which native to call and setup the arguments. 124465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Builtins::JavaScript native; 1245fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cc == eq) { 1246fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 124765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 124865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org native = Builtins::COMPARE; 124965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int ncr; // NaN compare result 1250fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (cc == lt || cc == le) { 125165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ncr = GREATER; 125265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 1253fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(cc == gt || cc == ge); // remaining cases 125465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ncr = LESS; 125565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 125665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(Smi::FromInt(ncr))); 125765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ push(r0); 125865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 125965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 126065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 126165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // tagged as a small integer. 12628e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ InvokeBuiltin(native, JUMP_FUNCTION); 1263fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1264fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ bind(&miss); 1265fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org GenerateMiss(masm); 126665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 126765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 126865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 1269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 1270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // We don't allow a GC during a store buffer overflow so there is no need to 1271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // store the registers in any particular way, but we do have to store and 1272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // restore them. 1273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ stm(db_w, sp, kCallerSaved | lr.bit()); 1274003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org 1275003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org const Register scratch = r1; 1276003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org 1277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (save_doubles_ == kSaveFPRegs) { 127877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org __ SaveFPRegs(sp, scratch); 1279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int argument_count = 1; 1281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int fp_argument_count = 0; 1282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com AllowExternalCallThatCantCauseGC scope(masm); 1284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 128532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ mov(r0, Operand(ExternalReference::isolate_address(masm->isolate()))); 1286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallCFunction( 1287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::store_buffer_overflow_function(masm->isolate()), 1288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com argument_count); 1289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (save_doubles_ == kSaveFPRegs) { 129077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org __ RestoreFPRegs(sp, scratch); 1291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). 1293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 1294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 129632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Generates code to call a C function to do a double operation. 129732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// This code never falls through, but returns with a heap number containing 129832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// the result in r0. 129932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Register heapnumber_result must be a heap number in which the 130032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// result of the operation will be stored. 130132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// Requires the following layout on entry: 130232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// d0: Left value. 130332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// d1: Right value. 130432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org// If soft float ABI, use also r0, r1, r2, r3. 130532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.orgstatic void CallCCodeForDoubleOperation(MacroAssembler* masm, 130632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org Token::Value op, 130732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org Register heap_number_result, 130832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org Register scratch) { 130932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Assert that heap_number_result is callee-saved. 131032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // We currently always use r5 to pass it. 131132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org ASSERT(heap_number_result.is(r5)); 131232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org 131332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Push the current return address before the C call. Return will be 131432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // through pop(pc) below. 131532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ push(lr); 131632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ PrepareCallCFunction(0, 2, scratch); 131732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org if (!masm->use_eabi_hardfloat()) { 131832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vmov(r0, r1, d0); 131932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vmov(r2, r3, d1); 132032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org } 132132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org { 132232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 132332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ CallCFunction( 132432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2); 132532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org } 132632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Store answer in the overwritable heap number. Double returned in 132732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // registers r0 and r1 or in d0. 132832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org if (masm->use_eabi_hardfloat()) { 132932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vstr(d0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); 133032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org } else { 133132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ Strd(r0, r1, 133232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org FieldMemOperand(heap_number_result, HeapNumber::kValueOffset)); 133332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org } 133432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Place heap_number_result in r0 and return to the pushed return address. 133532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ mov(r0, Operand(heap_number_result)); 133632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ pop(pc); 133732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org} 133832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org 133932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org 1340fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub::Initialize() { 1341e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org platform_specific_bit_ = true; // VFP2 is a base requirement for V8 1342fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org} 1343fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1344fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 134540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 1346378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Label get_result; 1347378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1348378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ Push(r1, r0); 1349378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1350378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ mov(r2, Operand(Smi::FromInt(MinorKey()))); 1351fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ push(r2); 1352378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1353378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ TailCallExternalReference( 135440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org ExternalReference(IC_Utility(IC::kBinaryOp_Patch), 1355ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org masm->isolate()), 1356fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 3, 1357378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1); 1358378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 1359378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1360378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 136140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateTypeTransitionWithSavedArgs( 1362378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org MacroAssembler* masm) { 1363a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org UNIMPLEMENTED(); 1364378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 1365378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1366378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1367fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm, 1368fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Token::Value op) { 1369378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register left = r1; 1370378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register right = r0; 1371378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register scratch1 = r7; 1372378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register scratch2 = r9; 1373378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1374378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org ASSERT(right.is(r0)); 1375378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org STATIC_ASSERT(kSmiTag == 0); 1376378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1377378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Label not_smi_result; 1378fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org switch (op) { 1379378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org case Token::ADD: 1380378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ add(right, left, Operand(right), SetCC); // Add optimistically. 1381378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ Ret(vc); 1382378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ sub(right, right, Operand(left)); // Revert optimistic add. 1383378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org break; 1384378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org case Token::SUB: 1385378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. 1386378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ Ret(vc); 1387378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ sub(right, left, Operand(right)); // Revert optimistic subtract. 1388378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org break; 1389378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org case Token::MUL: 1390378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Remove tag from one of the operands. This way the multiplication result 1391378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // will be a smi if it fits the smi range. 1392378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ SmiUntag(ip, right); 1393378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Do multiplication 1394378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // scratch1 = lower 32 bits of ip * left. 1395378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // scratch2 = higher 32 bits of ip * left. 1396378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ smull(scratch1, scratch2, left, ip); 1397378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Check for overflowing the smi range - no overflow if higher 33 bits of 1398378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // the result are identical. 1399378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ mov(ip, Operand(scratch1, ASR, 31)); 1400378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ cmp(ip, Operand(scratch2)); 1401378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ b(ne, ¬_smi_result); 1402378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Go slow on zero result to handle -0. 140359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(scratch1, Operand::Zero()); 1404378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ mov(right, Operand(scratch1), LeaveCC, ne); 1405378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ Ret(ne); 1406378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // We need -0 if we were multiplying a negative number with 0 to get 0. 1407378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // We know one of them was zero. 1408378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ add(scratch2, right, Operand(left), SetCC); 1409378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl); 1410378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ Ret(pl); // Return smi 0 if the non-zero one was positive. 1411378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // We fall through here if we multiplied a negative number with 0, because 1412378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // that would mean we should produce -0. 1413378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org break; 1414a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org case Token::DIV: { 1415a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org Label div_with_sdiv; 1416a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1417a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for 0 divisor. 141859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(right, Operand::Zero()); 1419a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(eq, ¬_smi_result); 1420a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 142131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org // Check for power of two on the right hand side. 1422a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ sub(scratch1, right, Operand(1)); 1423a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ tst(scratch1, right); 1424a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org if (CpuFeatures::IsSupported(SUDIV)) { 1425a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, &div_with_sdiv); 1426a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for no remainder. 1427a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ tst(left, scratch1); 1428a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, ¬_smi_result); 1429a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for positive left hand side. 143059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(left, Operand::Zero()); 1431a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(mi, &div_with_sdiv); 1432a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } else { 1433a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, ¬_smi_result); 1434a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for positive and no remainder. 1435a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ orr(scratch2, scratch1, Operand(0x80000000u)); 1436a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ tst(left, scratch2); 1437a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, ¬_smi_result); 1438a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 143931b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 144031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org // Perform division by shifting. 1441b228be01a466e0ba4d8389148671d196b2081f76mstarzinger@chromium.org __ clz(scratch1, scratch1); 144231b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org __ rsb(scratch1, scratch1, Operand(31)); 144331b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org __ mov(right, Operand(left, LSR, scratch1)); 144431b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org __ Ret(); 1445a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1446a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org if (CpuFeatures::IsSupported(SUDIV)) { 1447837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org CpuFeatureScope scope(masm, SUDIV); 1448a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org Label result_not_zero; 1449a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1450a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ bind(&div_with_sdiv); 1451a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Do division. 1452a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ sdiv(scratch1, left, right); 1453a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check that the remainder is zero. 1454a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ mls(scratch2, scratch1, right, left); 145559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(scratch2, Operand::Zero()); 1456a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, ¬_smi_result); 1457a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for negative zero result. 145859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(scratch1, Operand::Zero()); 1459a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, &result_not_zero); 146059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(right, Operand::Zero()); 1461a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(lt, ¬_smi_result); 1462a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ bind(&result_not_zero); 1463a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for the corner case of dividing the most negative smi by -1. 1464a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ cmp(scratch1, Operand(0x40000000)); 1465a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(eq, ¬_smi_result); 1466a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Tag and return the result. 1467a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ SmiTag(right, scratch1); 1468a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ Ret(); 1469a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 147031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org break; 1471a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 1472a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org case Token::MOD: { 1473a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org Label modulo_with_sdiv; 1474a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1475a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org if (CpuFeatures::IsSupported(SUDIV)) { 1476a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for x % 0. 147759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(right, Operand::Zero()); 1478a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(eq, ¬_smi_result); 1479a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1480a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for two positive smis. 1481a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ orr(scratch1, left, Operand(right)); 1482a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ tst(scratch1, Operand(0x80000000u)); 1483a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, &modulo_with_sdiv); 1484a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1485a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for power of two on the right hand side. 1486a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ sub(scratch1, right, Operand(1)); 1487a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ tst(scratch1, right); 1488a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, &modulo_with_sdiv); 1489a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } else { 1490a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for two positive smis. 1491a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ orr(scratch1, left, Operand(right)); 1492a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ tst(scratch1, Operand(0x80000000u)); 1493a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ b(ne, ¬_smi_result); 149431b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 1495a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Check for power of two on the right hand side. 1496a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ JumpIfNotPowerOfTwoOrZero(right, scratch1, ¬_smi_result); 1497a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 149831b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 1499a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Perform modulus by masking (scratch1 contains right - 1). 150031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org __ and_(right, left, Operand(scratch1)); 150131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org __ Ret(); 1502a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 1503a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org if (CpuFeatures::IsSupported(SUDIV)) { 1504837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org CpuFeatureScope scope(masm, SUDIV); 1505a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ bind(&modulo_with_sdiv); 1506a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ mov(scratch2, right); 1507a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Perform modulus with sdiv and mls. 1508a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ sdiv(scratch1, left, right); 1509a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ mls(right, scratch1, right, left); 1510a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Return if the result is not 0. 151159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(right, Operand::Zero()); 1512a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ Ret(ne); 1513a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // The result is 0, check for -0 case. 151459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(left, Operand::Zero()); 1515a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ Ret(pl); 1516a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // This is a -0 case, restore the value of right. 1517a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ mov(right, scratch2); 1518a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // We fall through here to not_smi_result to produce -0. 1519a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 152031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org break; 1521a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 152283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_OR: 152383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ orr(right, left, Operand(right)); 152483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ Ret(); 152583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 152683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_AND: 152783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ and_(right, left, Operand(right)); 152883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ Ret(); 152983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 153083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_XOR: 153183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ eor(right, left, Operand(right)); 153283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ Ret(); 153383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 1534496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SAR: 1535496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Remove tags from right operand. 1536496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ GetLeastBitsFromSmi(scratch1, right, 5); 1537496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ mov(right, Operand(left, ASR, scratch1)); 1538496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Smi tag result. 1539496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ bic(right, right, Operand(kSmiTagMask)); 1540496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ Ret(); 1541496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org break; 1542496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SHR: 1543496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Remove tags from operands. We can't do this on a 31 bit number 1544496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // because then the 0s get shifted into bit 30 instead of bit 31. 1545496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ SmiUntag(scratch1, left); 1546496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ GetLeastBitsFromSmi(scratch2, right, 5); 1547496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ mov(scratch1, Operand(scratch1, LSR, scratch2)); 1548496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Unsigned shift is not allowed to produce a negative number, so 1549496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // check the sign bit and the sign bit after Smi tagging. 1550496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ tst(scratch1, Operand(0xc0000000)); 1551496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ b(ne, ¬_smi_result); 1552496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Smi tag result. 1553496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ SmiTag(right, scratch1); 1554496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ Ret(); 1555496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org break; 1556496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SHL: 1557496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Remove tags from operands. 1558496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ SmiUntag(scratch1, left); 1559496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ GetLeastBitsFromSmi(scratch2, right, 5); 1560496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ mov(scratch1, Operand(scratch1, LSL, scratch2)); 1561496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Check that the signed result fits in a Smi. 1562bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ TrySmiTag(right, scratch1, ¬_smi_result); 1563496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ Ret(); 1564496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org break; 1565378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org default: 1566378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org UNREACHABLE(); 1567378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } 1568378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(¬_smi_result); 1569378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 1570378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1571378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1572fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, 1573fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register result, 1574fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register heap_number_map, 1575fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register scratch1, 1576fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register scratch2, 1577fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label* gc_required, 1578fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org OverwriteMode mode); 1579fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1580fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 1581fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, 1582fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpIC::TypeInfo left_type, 1583fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpIC::TypeInfo right_type, 1584fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org bool smi_operands, 1585fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label* not_numbers, 1586fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label* gc_required, 1587fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label* miss, 1588fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Token::Value op, 1589fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org OverwriteMode mode) { 159031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org Register left = r1; 159131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org Register right = r0; 1592f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org Register scratch1 = r6; 1593f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org Register scratch2 = r7; 1594b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org Register scratch3 = r4; 159531b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 159683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org ASSERT(smi_operands || (not_numbers != NULL)); 1597c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org if (smi_operands) { 1598c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org __ AssertSmi(left); 1599c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org __ AssertSmi(right); 160083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 1601fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (left_type == BinaryOpIC::SMI) { 1602fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(left, miss); 1603fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 1604fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (right_type == BinaryOpIC::SMI) { 1605fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(right, miss); 1606fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 160731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 1608f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org Register heap_number_map = r9; 160931b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 161031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 1611fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org switch (op) { 161283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::ADD: 161383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::SUB: 161483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::MUL: 161583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::DIV: 161683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::MOD: { 161783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Allocate new heap number for result. 161883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org Register result = r5; 1619fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateHeapResultAllocation( 1620fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, result, heap_number_map, scratch1, scratch2, gc_required, mode); 162183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 162232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Load left and right operands into d0 and d1. 162383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org if (smi_operands) { 1624bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d1, right); 1625bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d0, left); 162683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } else { 162732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Load right operand into d1. 1628fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (right_type == BinaryOpIC::INT32) { 162932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumberAsInt32Double( 163032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org right, d1, heap_number_map, scratch1, d8, miss); 1631fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } else { 16328432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; 163332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumber(right, d1, heap_number_map, scratch1, fail); 1634fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 163532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // Load left operand into d0. 1636fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (left_type == BinaryOpIC::INT32) { 163732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumberAsInt32Double( 163832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org left, d0, heap_number_map, scratch1, d8, miss); 1639fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } else { 16408432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; 164132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumber( 164232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org left, d0, heap_number_map, scratch1, fail); 1643fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 164483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 164531b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 164683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Calculate the result. 164732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org if (op != Token::MOD) { 164883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Using VFP registers: 164932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // d0: Left value 165032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // d1: Right value 1651fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org switch (op) { 165283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::ADD: 165332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vadd(d5, d0, d1); 165483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 165583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::SUB: 165632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vsub(d5, d0, d1); 165783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 165883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::MUL: 165932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vmul(d5, d0, d1); 166083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 166183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::DIV: 166232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vdiv(d5, d0, d1); 166383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 166483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org default: 166583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org UNREACHABLE(); 166683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 166731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org 166883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ sub(r0, result, Operand(kHeapObjectTag)); 166983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ vstr(d5, r0, HeapNumber::kValueOffset); 167083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ add(r0, r0, Operand(kHeapObjectTag)); 167183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ Ret(); 167283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } else { 16739ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Call the C function to handle the double operation. 167432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org CallCCodeForDoubleOperation(masm, op, result, scratch1); 1675160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org if (FLAG_debug_code) { 1676160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ stop("Unreachable code."); 1677160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org } 167883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 167983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 168083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 168183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_OR: 168283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_XOR: 1683496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::BIT_AND: 1684496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SAR: 1685496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SHR: 1686496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SHL: { 168783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org if (smi_operands) { 168883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ SmiUntag(r3, left); 168983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ SmiUntag(r2, right); 169083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } else { 169183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Convert operands to 32-bit integers. Right in r2 and left in r3. 169232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ ConvertNumberToInt32( 169332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org left, r3, heap_number_map, 169432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org scratch1, scratch2, scratch3, d0, d1, not_numbers); 169532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ ConvertNumberToInt32( 169632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org right, r2, heap_number_map, 169732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org scratch1, scratch2, scratch3, d0, d1, not_numbers); 169883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 1699496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org 1700496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org Label result_not_a_smi; 1701fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org switch (op) { 170283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_OR: 170383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ orr(r2, r3, Operand(r2)); 170483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 170583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_XOR: 170683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ eor(r2, r3, Operand(r2)); 170783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 170883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org case Token::BIT_AND: 170983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ and_(r2, r3, Operand(r2)); 171083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 1711496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SAR: 1712496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Use only the 5 least significant bits of the shift count. 1713496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ GetLeastBitsFromInt32(r2, r2, 5); 1714496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ mov(r2, Operand(r3, ASR, r2)); 1715496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org break; 1716496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SHR: 1717496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Use only the 5 least significant bits of the shift count. 1718496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ GetLeastBitsFromInt32(r2, r2, 5); 1719496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ mov(r2, Operand(r3, LSR, r2), SetCC); 1720496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // SHR is special because it is required to produce a positive answer. 1721496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // The code below for writing into heap numbers isn't capable of 1722496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // writing the register as an unsigned int so we go to slow case if we 1723496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // hit this case. 1724e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(mi, &result_not_a_smi); 1725496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org break; 1726496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org case Token::SHL: 1727496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Use only the 5 least significant bits of the shift count. 1728496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ GetLeastBitsFromInt32(r2, r2, 5); 1729496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ mov(r2, Operand(r3, LSL, r2)); 1730496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org break; 173183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org default: 173283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org UNREACHABLE(); 173383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 173483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 173583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Check that the *signed* result fits in a smi. 1736bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ TrySmiTag(r0, r2, &result_not_a_smi); 173783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ Ret(); 173883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 173983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Allocate new heap number for result. 174083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ bind(&result_not_a_smi); 17413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Register result = r5; 17423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (smi_operands) { 17433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ AllocateHeapNumber( 17443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org result, scratch1, scratch2, heap_number_map, gc_required); 17453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } else { 1746fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateHeapResultAllocation( 1747fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, result, heap_number_map, scratch1, scratch2, gc_required, 1748fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org mode); 17493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 175083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 175183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // r2: Answer as signed int32. 175283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // r5: Heap number to write answer into. 175383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 175483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Nothing can go wrong now, so move the heap number to r0, which is the 175583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // result. 175683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ mov(r0, Operand(r5)); 175783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 1758e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As 1759e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // mentioned above SHR needs to always produce a positive result. 1760e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vmov(s0, r2); 1761e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (op == Token::SHR) { 1762e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vcvt_f64_u32(d0, s0); 176383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } else { 1764e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vcvt_f64_s32(d0, s0); 176583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 1766e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r3, r0, Operand(kHeapObjectTag)); 1767e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vstr(d0, r3, HeapNumber::kValueOffset); 1768e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ Ret(); 176983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org break; 177083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org } 177183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org default: 177283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org UNREACHABLE(); 1773378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } 1774378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 1775378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1776378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1777378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// Generate the smi code. If the operation on smis are successful this return is 1778378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// generated. If the result is not a smi and heap number allocation is not 1779378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org// requested the code falls through. If number allocation is requested but a 1780fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org// heap number cannot be allocated the code jumps to the label gc_required. 1781fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateSmiCode( 178240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org MacroAssembler* masm, 1783160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Label* use_runtime, 1784378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Label* gc_required, 1785fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Token::Value op, 1786fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results, 1787fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org OverwriteMode mode) { 1788378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Label not_smis; 1789378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1790378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register left = r1; 1791378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register right = r0; 1792378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register scratch1 = r7; 1793378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1794378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Perform combined smi check on both operands. 1795378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ orr(scratch1, left, Operand(right)); 17967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfNotSmi(scratch1, ¬_smis); 1797378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 179831b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org // If the smi-smi operation results in a smi return is generated. 1799fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateSmiSmiOperation(masm, op); 1800378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1801378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // If heap number results are possible generate the result in an allocated 1802378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // heap number. 1803fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) { 1804fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateFPOperation( 1805fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true, 1806fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org use_runtime, gc_required, ¬_smis, op, mode); 1807378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } 1808378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(¬_smis); 1809378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 1810378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1811378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 181240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 1813d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Label right_arg_changed, call_runtime; 1814d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 18151510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (op_ == Token::MOD && encoded_right_arg_.has_value) { 1816d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // It is guaranteed that the value will fit into a Smi, because if it 1817d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // didn't, we wouldn't be here, see BinaryOp_Patch. 1818d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ cmp(r0, Operand(Smi::FromInt(fixed_right_arg_value()))); 1819d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ b(ne, &right_arg_changed); 1820d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 1821378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 182240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org if (result_type_ == BinaryOpIC::UNINITIALIZED || 182340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org result_type_ == BinaryOpIC::SMI) { 1824378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Only allow smi results. 1825fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateSmiCode( 1826fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_); 1827378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } else { 1828378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Allow heap number result and don't make a transition if a heap number 1829378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // cannot be allocated. 1830fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateSmiCode( 1831fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, 1832fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org mode_); 1833378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } 1834378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1835378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Code falls through if the result is not returned as either a smi or heap 1836378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // number. 1837d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ bind(&right_arg_changed); 1838378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org GenerateTypeTransition(masm); 1839378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1840378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(&call_runtime); 18414e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org { 18424e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 18434e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPush(masm); 18444e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateCallRuntime(masm); 18454e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 18464e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ Ret(); 1847378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 1848378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 1849378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 185040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { 1851160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Label call_runtime; 1852fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING); 1853160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org ASSERT(op_ == Token::ADD); 1854160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org // If both arguments are strings, call the string add stub. 1855160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org // Otherwise, do a transition. 1856160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 1857160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org // Registers containing left and right operands respectively. 1858160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Register left = r1; 1859160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Register right = r0; 1860160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 1861160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org // Test if left operand is a string. 1862160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ JumpIfSmi(left, &call_runtime); 1863160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); 1864160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ b(ge, &call_runtime); 1865160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 1866160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org // Test if right operand is a string. 1867160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ JumpIfSmi(right, &call_runtime); 1868160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); 1869160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ b(ge, &call_runtime); 1870160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 1871ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org StringAddStub string_add_stub( 1872ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME)); 1873160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org GenerateRegisterArgsPush(masm); 1874160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ TailCallStub(&string_add_stub); 1875160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 1876160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ bind(&call_runtime); 1877160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org GenerateTypeTransition(masm); 1878160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org} 1879160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 1880160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 188140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { 1882fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); 1883378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 18849ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Register left = r1; 18859ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Register right = r0; 18869ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Register scratch1 = r7; 18879ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Register scratch2 = r9; 1888fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org LowDwVfpRegister double_scratch = d0; 18899ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 18909ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Register heap_number_result = no_reg; 18919ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Register heap_number_map = r6; 18929ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 18939ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 18949ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Label call_runtime; 18959ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Labels for type transition, used for wrong input or output types. 18969ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Both label are currently actually bound to the same position. We use two 18979ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // different label to differentiate the cause leading to type transition. 18989ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Label transition; 18999ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 19009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Smi-smi fast case. 19019ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Label skip; 19029ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ orr(scratch1, left, right); 19039ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ JumpIfNotSmi(scratch1, &skip); 1904fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateSmiSmiOperation(masm, op_); 19059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Fall through if the result is not a smi. 19069ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ bind(&skip); 19079ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 19089ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org switch (op_) { 19099ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::ADD: 19109ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SUB: 19119ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::MUL: 19129ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::DIV: 19139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::MOD: { 1914fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // It could be that only SMIs have been seen at either the left 1915fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // or the right operand. For precise type feedback, patch the IC 1916fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // again if this changes. 1917fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (left_type_ == BinaryOpIC::SMI) { 1918fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(left, &transition); 1919fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 1920fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (right_type_ == BinaryOpIC::SMI) { 1921fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(right, &transition); 1922fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 19237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Load both operands and check that they are 32-bit integer. 19247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Jump to type transition if they are not. The registers r0 and r1 (right 19257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // and left) are preserved for the runtime call. 192632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumberAsInt32Double( 192732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org right, d1, heap_number_map, scratch1, d8, &transition); 192832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumberAsInt32Double( 192932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org left, d0, heap_number_map, scratch1, d8, &transition); 193032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org 193132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org if (op_ != Token::MOD) { 19329ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Label return_heap_number; 19339ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org switch (op_) { 19349ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::ADD: 193532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vadd(d5, d0, d1); 19369ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 19379ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SUB: 193832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vsub(d5, d0, d1); 19399ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 19409ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::MUL: 194132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vmul(d5, d0, d1); 19429ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 19439ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::DIV: 194432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vdiv(d5, d0, d1); 19459ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 19469ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org default: 19479ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org UNREACHABLE(); 19489ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 19499ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 1950837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org if (result_type_ <= BinaryOpIC::INT32) { 1951837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org __ TryDoubleToInt32Exact(scratch1, d5, d8); 1952837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org // If the ne condition is set, result does 1953837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org // not fit in a 32-bit integer. 1954837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org __ b(ne, &transition); 1955837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org // Try to tag the result as a Smi, return heap number on overflow. 1956837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org __ SmiTag(scratch1, SetCC); 1957837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org __ b(vs, &return_heap_number); 1958837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org // Check for minus zero, transition in that case (because we need 1959837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org // to return a heap number). 19607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Label not_zero; 1961837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org ASSERT(kSmiTag == 0); 19627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ b(ne, ¬_zero); 1963fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org __ VmovHigh(scratch2, d5); 19647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ tst(scratch2, Operand(HeapNumber::kSignMask)); 1965837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org __ b(ne, &transition); 19667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ bind(¬_zero); 1967837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org __ mov(r0, scratch1); 19689ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ Ret(); 19699ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 19709ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 1971d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com __ bind(&return_heap_number); 1972d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com // Return a heap number, or fall through to type transition or runtime 1973d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com // call if we can't. 197432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org // We are using vfp registers so r5 is available. 197532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org heap_number_result = r5; 197632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org BinaryOpStub_GenerateHeapResultAllocation(masm, 197732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org heap_number_result, 197832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org heap_number_map, 197932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org scratch1, 198032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org scratch2, 198132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org &call_runtime, 198232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org mode_); 198332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ sub(r0, heap_number_result, Operand(kHeapObjectTag)); 198432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ vstr(d5, r0, HeapNumber::kValueOffset); 198532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ mov(r0, heap_number_result); 198632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ Ret(); 19879ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 19889ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // A DIV operation expecting an integer result falls through 19899ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // to type transition. 19909ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 19919ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } else { 19921510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (encoded_right_arg_.has_value) { 1993d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ Vmov(d8, fixed_right_arg_value(), scratch1); 1994d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ VFPCompareAndSetFlags(d1, d8); 1995d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ b(ne, &transition); 1996d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 1997d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 19989ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // We preserved r0 and r1 to be able to call runtime. 19999ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Save the left value on the stack. 20009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ Push(r5, r4); 20019ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20023847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com Label pop_and_call_runtime; 20033847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com 20049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Allocate a heap number to store the result. 20059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org heap_number_result = r5; 2006fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateHeapResultAllocation(masm, 2007fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org heap_number_result, 2008fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org heap_number_map, 2009fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org scratch1, 2010fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org scratch2, 2011fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org &pop_and_call_runtime, 2012fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org mode_); 20139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20149ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Load the left value from the value saved on the stack. 20159ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ Pop(r1, r0); 20169ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20179ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Call the C function to handle the double operation. 201832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1); 2019160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org if (FLAG_debug_code) { 2020160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ stop("Unreachable code."); 2021160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org } 20223847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com 20233847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com __ bind(&pop_and_call_runtime); 20243847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com __ Drop(2); 20253847bd5ff857259e945a01d75fdb383e2351d166erik.corry@gmail.com __ b(&call_runtime); 20269ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 20279ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20289ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20299ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 20309ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20319ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::BIT_OR: 20329ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::BIT_XOR: 20339ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::BIT_AND: 20349ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SAR: 20359ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SHR: 20369ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SHL: { 20379ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org Label return_heap_number; 20389ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // Convert operands to 32-bit integers. Right in r2 and left in r3. The 20399ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // registers r0 and r1 (right and left) are preserved for the runtime 20409ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // call. 204132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumberAsInt32(left, r3, heap_number_map, 204232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org scratch1, d0, d1, &transition); 204332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ LoadNumberAsInt32(right, r2, heap_number_map, 204432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org scratch1, d0, d1, &transition); 20459ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20469ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // The ECMA-262 standard specifies that, for shift operations, only the 20479ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // 5 least significant bits of the shift value should be used. 20489ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org switch (op_) { 20499ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::BIT_OR: 20509ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ orr(r2, r3, Operand(r2)); 20519ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20529ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::BIT_XOR: 20539ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ eor(r2, r3, Operand(r2)); 20549ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20559ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::BIT_AND: 20569ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ and_(r2, r3, Operand(r2)); 20579ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20589ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SAR: 20599ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ and_(r2, r2, Operand(0x1f)); 20609ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ mov(r2, Operand(r3, ASR, r2)); 20619ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20629ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SHR: 20639ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ and_(r2, r2, Operand(0x1f)); 20649ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ mov(r2, Operand(r3, LSR, r2), SetCC); 20659ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // SHR is special because it is required to produce a positive answer. 20669ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // We only get a negative result if the shift value (r2) is 0. 20679ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // This result cannot be respresented as a signed 32-bit integer, try 20689ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org // to return a heap number if we can. 2069e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(mi, (result_type_ <= BinaryOpIC::INT32) 2070e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ? &transition 2071e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org : &return_heap_number); 20729ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20739ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org case Token::SHL: 20749ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ and_(r2, r2, Operand(0x1f)); 20759ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ mov(r2, Operand(r3, LSL, r2)); 20769ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 20779ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org default: 20789ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org UNREACHABLE(); 20799ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 20809ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 2081bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org // Check if the result fits in a smi. If not try to return a heap number. 2082bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org // (We know the result is an int32). 2083bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ TrySmiTag(r0, r2, &return_heap_number); 20849ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ Ret(); 20859ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 20869ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ bind(&return_heap_number); 2087160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org heap_number_result = r5; 2088fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateHeapResultAllocation(masm, 2089fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org heap_number_result, 2090fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org heap_number_map, 2091fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org scratch1, 2092fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org scratch2, 2093fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org &call_runtime, 2094fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org mode_); 2095160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 2096e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (op_ != Token::SHR) { 2097e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Convert the result to a floating point value. 2098e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vmov(double_scratch.low(), r2); 2099e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vcvt_f64_s32(double_scratch, double_scratch.low()); 21009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } else { 2101e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // The result must be interpreted as an unsigned 32-bit integer. 2102e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vmov(double_scratch.low(), r2); 2103e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vcvt_f64_u32(double_scratch, double_scratch.low()); 21049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 21059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 2106e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Store the result. 2107e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r0, heap_number_result, Operand(kHeapObjectTag)); 2108e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vstr(double_scratch, r0, HeapNumber::kValueOffset); 2109e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, heap_number_result); 2110e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ Ret(); 2111e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 21129ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org break; 21139ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 21149ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 21159ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org default: 21169ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org UNREACHABLE(); 21179ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 21189ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 2119d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com // We never expect DIV to yield an integer result, so we always generate 2120d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com // type transition code for DIV operations expecting an integer result: the 2121d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com // code will fall through to this type transition. 2122d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com if (transition.is_linked() || 2123d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com ((op_ == Token::DIV) && (result_type_ <= BinaryOpIC::INT32))) { 21249ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ bind(&transition); 21259ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org GenerateTypeTransition(masm); 21269ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org } 21279ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org 21289ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org __ bind(&call_runtime); 21294e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org { 21304e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 21314e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPush(masm); 21324e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateCallRuntime(masm); 21334e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 21344e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ Ret(); 2135378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 2136378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2137378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 213840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 2139b08986cb66c3f6687247cb6da186c1e73057e399whesse@chromium.org Label call_runtime; 2140378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 21417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org if (op_ == Token::ADD) { 21427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Handle string addition here, because it is the only operation 21437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // that does not do a ToNumber conversion on the operands. 21447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org GenerateAddStrings(masm); 21457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 21467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 21477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org // Convert oddball arguments to numbers. 21487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org Label check, done; 21497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); 21507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ b(ne, &check); 21517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org if (Token::IsBitOp(op_)) { 21527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ mov(r1, Operand(Smi::FromInt(0))); 21537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } else { 21547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ LoadRoot(r1, Heap::kNanValueRootIndex); 21557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 21567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ jmp(&done); 21577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ bind(&check); 21587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 21597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ b(ne, &done); 21607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org if (Token::IsBitOp(op_)) { 21617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ mov(r0, Operand(Smi::FromInt(0))); 21627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } else { 21637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ LoadRoot(r0, Heap::kNanValueRootIndex); 21647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org } 21657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org __ bind(&done); 21667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 21678432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org GenerateNumberStub(masm); 21687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 21697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 21707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 21718432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) { 2172fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label call_runtime, transition; 2173fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateFPOperation( 2174fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, left_type_, right_type_, false, 2175fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org &transition, &call_runtime, &transition, op_, mode_); 2176fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 2177fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ bind(&transition); 2178fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org GenerateTypeTransition(masm); 2179378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2180378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(&call_runtime); 21814e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org { 21824e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 21834e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPush(masm); 21844e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateCallRuntime(masm); 21854e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 21864e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ Ret(); 2187378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 2188378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2189378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 219040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { 2191fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label call_runtime, call_string_add_or_runtime, transition; 2192378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2193fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateSmiCode( 2194fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_); 2195378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2196fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org BinaryOpStub_GenerateFPOperation( 2197fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org masm, left_type_, right_type_, false, 2198fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org &call_string_add_or_runtime, &call_runtime, &transition, op_, mode_); 2199fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 2200fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ bind(&transition); 2201fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org GenerateTypeTransition(masm); 2202378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 22033a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(&call_string_add_or_runtime); 2204378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org if (op_ == Token::ADD) { 2205378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org GenerateAddStrings(masm); 2206378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } 2207378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 22083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(&call_runtime); 22094e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org { 22104e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 22114e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPush(masm); 22124e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateCallRuntime(masm); 22134e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 22144e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ Ret(); 2215378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 2216378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2217378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 221840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { 2219378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org ASSERT(op_ == Token::ADD); 22203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Label left_not_string, call_runtime; 2221378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2222378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register left = r1; 2223378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Register right = r0; 2224378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 22253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Check if left argument is a string. 22263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ JumpIfSmi(left, &left_not_string); 2227378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); 22283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ b(ge, &left_not_string); 2229378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2230ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org StringAddStub string_add_left_stub( 2231ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org (StringAddFlags)(STRING_ADD_CHECK_RIGHT | STRING_ADD_ERECT_FRAME)); 22323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org GenerateRegisterArgsPush(masm); 22333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ TailCallStub(&string_add_left_stub); 22343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 22353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Left operand is not a string, test right. 22363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(&left_not_string); 2237378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfSmi(right, &call_runtime); 2238378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); 2239378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ b(ge, &call_runtime); 2240378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2241ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org StringAddStub string_add_right_stub( 2242ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME)); 2243378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org GenerateRegisterArgsPush(masm); 22443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ TailCallStub(&string_add_right_stub); 2245378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2246378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // At least one argument is not a string. 2247378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(&call_runtime); 2248378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 2249378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2250378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2251fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, 2252fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register result, 2253fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register heap_number_map, 2254fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register scratch1, 2255fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register scratch2, 2256fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Label* gc_required, 2257fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org OverwriteMode mode) { 2258378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Code below will scratch result if allocation fails. To keep both arguments 2259378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // intact for the runtime call result cannot be one of these. 2260378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org ASSERT(!result.is(r0) && !result.is(r1)); 2261378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2262fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (mode == OVERWRITE_LEFT || mode == OVERWRITE_RIGHT) { 2263378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org Label skip_allocation, allocated; 2264fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Register overwritable_operand = mode == OVERWRITE_LEFT ? r1 : r0; 2265378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // If the overwritable operand is already an object, we skip the 2266378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // allocation of a heap number. 2267378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfNotSmi(overwritable_operand, &skip_allocation); 2268378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Allocate a heap number for the result. 2269378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ AllocateHeapNumber( 2270378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org result, scratch1, scratch2, heap_number_map, gc_required); 2271378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ b(&allocated); 2272378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(&skip_allocation); 2273378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org // Use object holding the overwritable operand for result. 2274378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ mov(result, Operand(overwritable_operand)); 2275378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ bind(&allocated); 2276378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } else { 2277fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(mode == NO_OVERWRITE); 2278378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ AllocateHeapNumber( 2279378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org result, scratch1, scratch2, heap_number_map, gc_required); 2280378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org } 2281378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org} 2282378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 2283378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org 228440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgvoid BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 2285378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ Push(r1, r0); 2286a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 2287a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 2288a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 228965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid TranscendentalCacheStub::Generate(MacroAssembler* masm) { 22908f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // Untagged case: double input in d2, double result goes 22918f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // into d2. 22928f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // Tagged case: tagged input on top of stack and in r0, 22938f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // tagged result (heap number) goes into r0. 22948f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 229565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label input_not_smi; 229665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label loaded; 22978f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org Label calculate; 22988f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org Label invalid_cache; 22998f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org const Register scratch0 = r9; 23008f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org const Register scratch1 = r7; 23018f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org const Register cache_entry = r0; 23028f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org const bool tagged = (argument_type_ == TAGGED); 230365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 2304e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (tagged) { 2305e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Argument is a number and is on stack and in r0. 2306e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Load argument and check if it is a smi. 2307e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ JumpIfNotSmi(r0, &input_not_smi); 2308e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 2309e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Input is a smi. Convert to double and load the low and high words 2310e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // of the double into r2, r3. 2311bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d7, r0); 2312bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ vmov(r2, r3, d7); 2313e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(&loaded); 2314e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 2315e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&input_not_smi); 2316e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Check if input is a HeapNumber. 2317e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ CheckMap(r0, 2318e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org r1, 2319e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Heap::kHeapNumberMapRootIndex, 2320e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org &calculate, 2321e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org DONT_DO_SMI_CHECK); 2322e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Input is a HeapNumber. Load it to a double register and store the 2323e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // low and high words into r2, r3. 2324e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset)); 2325e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vmov(r2, r3, d0); 2326e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } else { 2327e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Input is untagged double in d2. Output goes to d2. 2328e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vmov(r2, r3, d2); 2329e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 2330e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&loaded); 2331e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // r2 = low 32 bits of double value 2332e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // r3 = high 32 bits of double value 2333e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Compute hash (the shifts are arithmetic): 2334e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1); 2335e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ eor(r1, r2, Operand(r3)); 2336e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ eor(r1, r1, Operand(r1, ASR, 16)); 2337e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ eor(r1, r1, Operand(r1, ASR, 8)); 2338e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); 2339e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ And(r1, r1, Operand(TranscendentalCache::SubCache::kCacheSize - 1)); 2340e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 2341e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // r2 = low 32 bits of double value. 2342e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // r3 = high 32 bits of double value. 2343e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // r1 = TranscendentalCache::hash(double value). 2344e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Isolate* isolate = masm->isolate(); 2345e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ExternalReference cache_array = 2346e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org ExternalReference::transcendental_cache_array_address(isolate); 2347e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(cache_entry, Operand(cache_array)); 2348e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // cache_entry points to cache array. 2349e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org int cache_array_index 2350e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org = type_ * sizeof(isolate->transcendental_cache()->caches_[0]); 2351e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ ldr(cache_entry, MemOperand(cache_entry, cache_array_index)); 2352e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // r0 points to the cache for the type type_. 2353e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // If NULL, the cache hasn't been initialized yet, so go through runtime. 2354e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ cmp(cache_entry, Operand::Zero()); 2355e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(eq, &invalid_cache); 235665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 235765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef DEBUG 2358e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Check that the layout of cache elements match expectations. 2359e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org { TranscendentalCache::SubCache::Element test_elem[2]; 2360e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org char* elem_start = reinterpret_cast<char*>(&test_elem[0]); 2361e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); 2362e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); 2363e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); 2364e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); 2365e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. 2366e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org CHECK_EQ(0, elem_in0 - elem_start); 2367e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org CHECK_EQ(kIntSize, elem_in1 - elem_start); 2368e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org CHECK_EQ(2 * kIntSize, elem_out - elem_start); 2369e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 237065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif 237165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 2372e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12]. 2373e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ add(r1, r1, Operand(r1, LSL, 1)); 2374e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ add(cache_entry, cache_entry, Operand(r1, LSL, 2)); 2375e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Check if cache matches: Double value is stored in uint32_t[2] array. 2376e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ ldm(ia, cache_entry, r4.bit() | r5.bit() | r6.bit()); 2377e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ cmp(r2, r4); 2378e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ cmp(r3, r5, eq); 2379e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(ne, &calculate); 2380e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Cache hit. Load result, cleanup and return. 2381e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Counters* counters = masm->isolate()->counters(); 2382e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ IncrementCounter( 2383e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org counters->transcendental_cache_hit(), 1, scratch0, scratch1); 2384e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (tagged) { 2385e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Pop input value from stack and load result into r0. 2386e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ pop(); 2387e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(r6)); 2388e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } else { 2389e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Load result into d2. 2390e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset)); 2391e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 2392e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ Ret(); 23938f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 23948f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ bind(&calculate); 23951b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ IncrementCounter( 23961b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org counters->transcendental_cache_miss(), 1, scratch0, scratch1); 23978f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org if (tagged) { 23988f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ bind(&invalid_cache); 2399ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExternalReference runtime_function = 2400ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExternalReference(RuntimeFunction(), masm->isolate()); 2401ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ TailCallExternalReference(runtime_function, 1, 1); 24028f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org } else { 24038f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org Label no_update; 24048f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org Label skip_cache; 24058f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 24068f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // Call C function to calculate the result and update the cache. 240728583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org // r0: precalculated cache entry address. 240828583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org // r2 and r3: parts of the double value. 240928583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org // Store r0, r2 and r3 on stack for later before calling C function. 241028583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org __ Push(r3, r2, cache_entry); 24118f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org GenerateCallCFunction(masm, scratch0); 24128f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ GetCFunctionDoubleResult(d2); 24138f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 24148f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // Try to update the cache. If we cannot allocate a 24158f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // heap number, we return the result without updating. 241628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org __ Pop(r3, r2, cache_entry); 24178f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex); 24188f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ AllocateHeapNumber(r6, scratch0, scratch1, r5, &no_update); 24198f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ vstr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset)); 24208f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ stm(ia, cache_entry, r2.bit() | r3.bit() | r6.bit()); 24218f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ Ret(); 24228f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 24238f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ bind(&invalid_cache); 24248f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // The cache is invalid. Call runtime which will recreate the 24258f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // cache. 24268f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex); 24278f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ AllocateHeapNumber(r0, scratch0, scratch1, r5, &skip_cache); 24288f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ vstr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset)); 2429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 2430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 2431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(r0); 2432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(RuntimeFunction(), 1); 2433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 24348f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ vldr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset)); 24358f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ Ret(); 24368f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 24378f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ bind(&skip_cache); 24388f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // Call C function to calculate the result and answer directly 24398f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // without updating the cache. 24408f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org GenerateCallCFunction(masm, scratch0); 24418f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ GetCFunctionDoubleResult(d2); 24428f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ bind(&no_update); 24438f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 24448f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // We return the value in d2 without adding it to the cache, but 24458f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org // we cause a scavenging GC so that future allocations will succeed. 2446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 2447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 2448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 2449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocate an aligned object larger than a HeapNumber. 2450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT(4 * kPointerSize >= HeapNumber::kSize); 2451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(scratch0, Operand(4 * kPointerSize)); 2452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(scratch0); 2453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); 2454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 245565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 245665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 24578f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org} 24588f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org 245965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 24608f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.orgvoid TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm, 24618f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org Register scratch) { 2462ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Isolate* isolate = masm->isolate(); 2463ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 24648f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ push(lr); 24658e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ PrepareCallCFunction(0, 1, scratch); 24668e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org if (masm->use_eabi_hardfloat()) { 24678e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ vmov(d0, d2); 24688e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org } else { 24698e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ vmov(r0, r1, d2); 24708e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org } 2471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com AllowExternalCallThatCantCauseGC scope(masm); 24728f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org switch (type_) { 24738f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org case TranscendentalCache::SIN: 24748e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ CallCFunction(ExternalReference::math_sin_double_function(isolate), 24758e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org 0, 1); 24768f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org break; 24778f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org case TranscendentalCache::COS: 24788e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ CallCFunction(ExternalReference::math_cos_double_function(isolate), 24798e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org 0, 1); 24808f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org break; 24811b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org case TranscendentalCache::TAN: 24821b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ CallCFunction(ExternalReference::math_tan_double_function(isolate), 24831b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org 0, 1); 24841b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org break; 24858f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org case TranscendentalCache::LOG: 24868e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ CallCFunction(ExternalReference::math_log_double_function(isolate), 24878e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org 0, 1); 24888f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org break; 24898f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org default: 24908f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org UNIMPLEMENTED(); 24918f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org break; 24928f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org } 24938f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org __ pop(lr); 249465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 249565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 249665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 249765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgRuntime::FunctionId TranscendentalCacheStub::RuntimeFunction() { 249865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org switch (type_) { 249965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Add more cases when necessary. 250065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org case TranscendentalCache::SIN: return Runtime::kMath_sin; 250165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org case TranscendentalCache::COS: return Runtime::kMath_cos; 25021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org case TranscendentalCache::TAN: return Runtime::kMath_tan; 2503a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org case TranscendentalCache::LOG: return Runtime::kMath_log; 250465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org default: 250565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org UNIMPLEMENTED(); 250665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org return Runtime::kAbort; 250765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 250865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 250965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 251065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 251165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StackCheckStub::Generate(MacroAssembler* masm) { 25124a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org __ TailCallRuntime(Runtime::kStackGuard, 0, 1); 251365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 251465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 251565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 251656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvoid InterruptStub::Generate(MacroAssembler* masm) { 251756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org __ TailCallRuntime(Runtime::kInterrupt, 0, 1); 251856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org} 251956454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org 252056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org 25214d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.orgvoid MathPowStub::Generate(MacroAssembler* masm) { 252264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const Register base = r1; 252364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const Register exponent = r2; 252464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const Register heapnumbermap = r5; 252564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const Register heapnumber = r0; 2526a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org const DwVfpRegister double_base = d1; 2527a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org const DwVfpRegister double_exponent = d2; 2528a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org const DwVfpRegister double_result = d3; 2529a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org const DwVfpRegister double_scratch = d0; 253064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const SwVfpRegister single_scratch = s0; 253164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const Register scratch = r9; 253264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org const Register scratch2 = r7; 253364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 2534fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org Label call_runtime, done, int_exponent; 253564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org if (exponent_type_ == ON_STACK) { 253664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org Label base_is_smi, unpack_exponent; 253764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // The exponent and base are supplied as arguments on the stack. 253864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // This can only happen if the stub is called from non-optimized code. 253964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Load input parameters from stack to double registers. 25404d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ ldr(base, MemOperand(sp, 1 * kPointerSize)); 25414d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); 25424d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 254364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); 25444d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 2545fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); 25464d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); 25474d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ cmp(scratch, heapnumbermap); 25484d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ b(ne, &call_runtime); 254964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 25504d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); 255164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ jmp(&unpack_exponent); 255264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 255364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&base_is_smi); 2554fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ vmov(single_scratch, scratch); 255564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vcvt_f64_s32(double_base, single_scratch); 255664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&unpack_exponent); 25574d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 2558fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 25594d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 25604d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); 25614d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ cmp(scratch, heapnumbermap); 25624d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ b(ne, &call_runtime); 25634d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ vldr(double_exponent, 25644d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org FieldMemOperand(exponent, HeapNumber::kValueOffset)); 256564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } else if (exponent_type_ == TAGGED) { 256664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Base is already in double_base. 2567fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 256864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 256964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vldr(double_exponent, 257064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org FieldMemOperand(exponent, HeapNumber::kValueOffset)); 257164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } 257264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 257364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org if (exponent_type_ != INTEGER) { 257464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org Label int_exponent_convert; 257564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Detect integer exponents stored as double. 257664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vcvt_u32_f64(single_scratch, double_exponent); 257764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // We do not check for NaN or Infinity here because comparing numbers on 257864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // ARM correctly distinguishes NaNs. We end up calling the built-in. 257964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vcvt_f64_u32(double_scratch, single_scratch); 258064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ VFPCompareAndSetFlags(double_scratch, double_exponent); 258164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(eq, &int_exponent_convert); 258264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 258364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org if (exponent_type_ == ON_STACK) { 258464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Detect square root case. Crankshaft detects constant +/-0.5 at 258564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // compile time and uses DoMathPowHalf instead. We then skip this check 258664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // for non-constant cases of +/-0.5 as these hardly occur. 258764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org Label not_plus_half; 258864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 258964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Test for 0.5. 259033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_scratch, 0.5, scratch); 259164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ VFPCompareAndSetFlags(double_exponent, double_scratch); 259264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ne, ¬_plus_half); 259364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 259464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Calculates square root of base. Check for the special case of 259564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 259633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_scratch, -V8_INFINITY, scratch); 259764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ VFPCompareAndSetFlags(double_base, double_scratch); 259864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vneg(double_result, double_scratch, eq); 259964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(eq, &done); 260064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 260164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Add +0 to convert -0 to +0. 260264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vadd(double_scratch, double_base, kDoubleRegZero); 260364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vsqrt(double_result, double_scratch); 260464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ jmp(&done); 260564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 260664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(¬_plus_half); 260733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_scratch, -0.5, scratch); 260864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ VFPCompareAndSetFlags(double_exponent, double_scratch); 260964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ne, &call_runtime); 261064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 261164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Calculates square root of base. Check for the special case of 261264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 261333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_scratch, -V8_INFINITY, scratch); 261464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ VFPCompareAndSetFlags(double_base, double_scratch); 261564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vmov(double_result, kDoubleRegZero, eq); 261664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(eq, &done); 261764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 261864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Add +0 to convert -0 to +0. 261964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vadd(double_scratch, double_base, kDoubleRegZero); 262033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_result, 1.0, scratch); 262164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vsqrt(double_scratch, double_scratch); 262264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vdiv(double_result, double_result, double_scratch); 262364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ jmp(&done); 262464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } 26254d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 26264d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ push(lr); 2627c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 2628c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com AllowExternalCallThatCantCauseGC scope(masm); 262964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ PrepareCallCFunction(0, 2, scratch); 263064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ SetCallCDoubleArguments(double_base, double_exponent); 2631c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallCFunction( 2632c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::power_double_double_function(masm->isolate()), 2633c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 0, 2); 2634c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 263564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ pop(lr); 263664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ GetCFunctionDoubleResult(double_result); 263764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ jmp(&done); 263864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 263964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&int_exponent_convert); 264064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vcvt_u32_f64(single_scratch, double_exponent); 2641fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ vmov(scratch, single_scratch); 264264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } 264364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 264464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Calculate power with integer exponent. 264564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&int_exponent); 264664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 2647fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Get two copies of exponent in the registers scratch and exponent. 2648fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org if (exponent_type_ == INTEGER) { 2649fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ mov(scratch, exponent); 2650fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org } else { 2651fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Exponent has previously been stored into scratch as untagged integer. 2652fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ mov(exponent, scratch); 2653fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org } 265464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vmov(double_scratch, double_base); // Back up base. 265533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_result, 1.0, scratch2); 265664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 265764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Get absolute value of exponent. 265859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(scratch, Operand::Zero()); 265959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(scratch2, Operand::Zero(), LeaveCC, mi); 266064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ sub(scratch, scratch2, scratch, LeaveCC, mi); 266164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 266264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org Label while_true; 266364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&while_true); 266464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ mov(scratch, Operand(scratch, ASR, 1), SetCC); 266564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vmul(double_result, double_result, double_scratch, cs); 266664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vmul(double_scratch, double_scratch, double_scratch, ne); 266764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ne, &while_true); 266864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 266959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(exponent, Operand::Zero()); 267064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ge, &done); 267133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ vmov(double_scratch, 1.0, scratch); 267264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vdiv(double_result, double_scratch, double_result); 267364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Test whether result is zero. Bail out to check for subnormal result. 267464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 267564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ VFPCompareAndSetFlags(double_result, 0.0); 267664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ne, &done); 267764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // double_exponent may not containe the exponent value if the input was a 267864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // smi. We set it with exponent value before bailing out. 267964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vmov(single_scratch, exponent); 268064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ vcvt_f64_s32(double_exponent, single_scratch); 268164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 268264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Returning or bailing out. 268364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org Counters* counters = masm->isolate()->counters(); 268464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org if (exponent_type_ == ON_STACK) { 268564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // The arguments are still on the stack. 268664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&call_runtime); 268764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); 268864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 268964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // The stub is called from non-optimized code, which expects the result 269064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // as heap number in exponent. 269164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&done); 269264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ AllocateHeapNumber( 269364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); 26944d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org __ vstr(double_result, 26954d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); 269664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org ASSERT(heapnumber.is(r0)); 269764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 269864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ Ret(2); 269964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } else { 270064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ push(lr); 270164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org { 270264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org AllowExternalCallThatCantCauseGC scope(masm); 270364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ PrepareCallCFunction(0, 2, scratch); 270464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ SetCallCDoubleArguments(double_base, double_exponent); 270564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ CallCFunction( 270664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org ExternalReference::power_double_double_function(masm->isolate()), 270764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 0, 2); 270864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } 270964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ pop(lr); 271064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ GetCFunctionDoubleResult(double_result); 27114d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 271264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&done); 271364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 271464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ Ret(); 271564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org } 27164d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org} 27174d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 27184d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 27194d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.orgbool CEntryStub::NeedsImmovableCode() { 27204d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org return true; 27214d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org} 27224d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 27234d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org 2724c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool CEntryStub::IsPregenerated() { 2725c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && 2726c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com result_size_ == 1; 2727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 2728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 2729c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 27308432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 27318432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org CEntryStub::GenerateAheadOfTime(isolate); 27328432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); 27338432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2734e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 27358432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 27361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 2737bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 2738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 2739c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 2740c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 27418432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CodeStub::GenerateFPStubs(Isolate* isolate) { 2742e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org SaveFPRegsMode mode = kSaveFPRegs; 2743a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org CEntryStub save_doubles(1, mode); 2744a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org StoreBufferOverflowStub stub(mode); 2745a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // These stubs might already be in the snapshot, detect that and don't 2746a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // regenerate, which would lead to code stub initialization state being messed 2747a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // up. 2748750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Code* save_doubles_code; 2749750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { 2750750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org save_doubles_code = *save_doubles.GetCode(isolate); 2751a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 2752e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Code* store_buffer_overflow_code; 2753e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org if (!stub.FindCodeInCache(&store_buffer_overflow_code, isolate)) { 2754e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org store_buffer_overflow_code = *stub.GetCode(isolate); 2755e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org } 2756e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org save_doubles_code->set_is_pregenerated(true); 2757e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org store_buffer_overflow_code->set_is_pregenerated(true); 2758750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org isolate->set_fp_stubs_generated(true); 2759c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 2760c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 2761c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 27628432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 2763c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com CEntryStub stub(1, kDontSaveFPRegs); 27648432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org Handle<Code> code = stub.GetCode(isolate); 2765c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com code->set_is_pregenerated(true); 2766c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 2767c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 2768c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 276959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.orgstatic void JumpIfOOM(MacroAssembler* masm, 277059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org Register value, 277159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org Register scratch, 277259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org Label* oom_label) { 277359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3); 277459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org STATIC_ASSERT(kFailureTag == 3); 277559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ and_(scratch, value, Operand(0xf)); 277659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(scratch, Operand(0xf)); 277759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ b(eq, oom_label); 277859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org} 277959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 278059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 278165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CEntryStub::GenerateCore(MacroAssembler* masm, 278265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* throw_normal_exception, 278365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* throw_termination_exception, 278465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* throw_out_of_memory_exception, 278565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org bool do_gc, 27860ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org bool always_allocate) { 278765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: result parameter for PerformGC, if any 278865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r4: number of arguments including receiver (C callee-saved) 278965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r5: pointer to builtin function (C callee-saved) 279065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r6: pointer to the first argument (C callee-saved) 2791ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Isolate* isolate = masm->isolate(); 279265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 279365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (do_gc) { 279465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Passing r0. 27958e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ PrepareCallCFunction(1, 0, r1); 27968e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ CallCFunction(ExternalReference::perform_gc_function(isolate), 27978e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org 1, 0); 279865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 279965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 280065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ExternalReference scope_depth = 2801ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExternalReference::heap_always_allocate_scope_depth(isolate); 280265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (always_allocate) { 280365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(scope_depth)); 280465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, MemOperand(r0)); 280565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r1, r1, Operand(1)); 280665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, MemOperand(r0)); 280765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 280865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 280965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Call C built-in. 281065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0 = argc, r1 = argv 281165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(r4)); 281265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r1, Operand(r6)); 281365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 281493a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_HOST_ARCH_ARM 281565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 281665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int frame_alignment_mask = frame_alignment - 1; 281765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (FLAG_debug_code) { 281865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (frame_alignment > kPointerSize) { 281965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label alignment_as_expected; 282065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT(IsPowerOf2(frame_alignment)); 2821378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ tst(sp, Operand(frame_alignment_mask)); 282265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &alignment_as_expected); 282365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Don't use Check here, as it will call Runtime_Abort re-entering here. 282465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ stop("Unexpected alignment"); 282565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&alignment_as_expected); 282665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 282765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 282865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif 282965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 283032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ mov(r2, Operand(ExternalReference::isolate_address(isolate))); 2831ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 28326d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org // To let the GC traverse the return address of the exit frames, we need to 28336d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org // know where the return address is. The CEntryStub is unmovable, so 28346d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org // we can store the address on the stack to be able to find it again and 28356d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org // we never have to restore it, because it will not change. 28360ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org // Compute the return address in lr to return to after the jump below. Pc is 28370ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org // already at '+ 8' from the current instruction but return is after three 28380ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org // instructions so add another 4 to pc to get the return address. 28397028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org { 28407028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // Prevent literal pool emission before return address. 28417028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org Assembler::BlockConstPoolScope block_const_pool(masm); 28427028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org masm->add(lr, pc, Operand(4)); 28437028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org __ str(lr, MemOperand(sp, 0)); 28447028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org masm->Jump(r5); 28457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org } 284665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 2847e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ VFPEnsureFPSCRState(r2); 2848e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 284965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (always_allocate) { 285065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1 285165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // though (contain the result). 285265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r2, Operand(scope_depth)); 285365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, MemOperand(r2)); 285465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(r3, r3, Operand(1)); 285565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(r2)); 285665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 285765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 285865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // check for failure result 285965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label failure_returned; 286065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 286165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Lower 2 bits of r2 are 0 iff r0 has failure tag. 286265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r2, r0, Operand(1)); 286365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r2, Operand(kFailureTagMask)); 286465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &failure_returned); 286565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 286665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Exit C frame and return. 286765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0:r1: result 286865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp: stack pointer 286965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // fp: frame pointer 287049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Callee-saved register r4 still holds argc. 287149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ LeaveExitFrame(save_doubles_, r4); 287249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ mov(pc, lr); 287365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 287465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // check if we should retry or throw exception 287565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label retry; 287665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&failure_returned); 287765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); 287865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 287965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &retry); 288065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 288165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Special handling of out of memory exceptions. 288259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org JumpIfOOM(masm, r0, ip, throw_out_of_memory_exception); 288365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 2884e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Retrieve the pending exception. 288583e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 2886ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate))); 288765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(ip)); 2888e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 2889e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // See if we just retrieved an OOM exception. 2890e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org JumpIfOOM(masm, r0, ip, throw_out_of_memory_exception); 2891e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 2892e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Clear the pending exception. 2893e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r3, Operand(isolate->factory()->the_hole_value())); 2894e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 2895e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org isolate))); 289665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(ip)); 289765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 289865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Special handling of termination exceptions which are uncatchable 289965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // by javascript code. 2900ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ cmp(r0, Operand(isolate->factory()->termination_exception())); 290165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, throw_termination_exception); 290265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 290365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Handle normal exception. 290465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(throw_normal_exception); 290565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 290665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying 290765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 290865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 290965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 291065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CEntryStub::Generate(MacroAssembler* masm) { 291165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Called from JavaScript; parameters are on stack as if calling JS function 291265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: number of arguments including receiver 291365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: pointer to builtin function 291465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // fp: frame pointer (restored after C call) 291565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp: stack pointer (restored as callee's sp after C call) 291665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // cp: current context (C callee-saved) 291765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 29181510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 29191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 292065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Result returned in r0 or r0+r1 by default. 292165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 292265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // NOTE: Invocations of builtins may return failure objects 292365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // instead of a proper result. The builtin entry handles 292465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // this by performing a garbage collection and retrying the 292565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // builtin once. 292665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 292783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org // Compute the argv pointer in a callee-saved register. 292883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); 292983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ sub(r6, r6, Operand(kPointerSize)); 293083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 293165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Enter the exit frame that transitions from JavaScript to C++. 2932c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::MANUAL); 2933a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ EnterExitFrame(save_doubles_); 293465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 2935f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up argc and the builtin function in callee-saved registers. 293683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ mov(r4, Operand(r0)); 293783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ mov(r5, Operand(r1)); 293883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 293965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r4: number of arguments (C callee-saved) 294065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r5: pointer to builtin function (C callee-saved) 294165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r6: pointer to first argument (C callee-saved) 294265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 294365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label throw_normal_exception; 294465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label throw_termination_exception; 294565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label throw_out_of_memory_exception; 294665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 294765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Call into the runtime system. 294865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org GenerateCore(masm, 294965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_normal_exception, 295065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_termination_exception, 295165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_out_of_memory_exception, 295265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org false, 29530ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org false); 295465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 295565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Do space-specific GC and retry runtime call. 295665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org GenerateCore(masm, 295765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_normal_exception, 295865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_termination_exception, 295965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_out_of_memory_exception, 296065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org true, 29610ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org false); 296265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 296365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Do full GC and retry runtime call one final time. 296465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Failure* failure = Failure::InternalError(); 296565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(reinterpret_cast<int32_t>(failure))); 296665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org GenerateCore(masm, 296765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_normal_exception, 296865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_termination_exception, 296965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org &throw_out_of_memory_exception, 297065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org true, 29710ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org true); 297265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 297365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&throw_out_of_memory_exception); 297465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org // Set external caught exception to false. 297565a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org Isolate* isolate = masm->isolate(); 297665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, 297765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org isolate); 297859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r0, Operand(false, RelocInfo::NONE32)); 297965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ mov(r2, Operand(external_caught)); 298065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ str(r0, MemOperand(r2)); 298165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org 298265a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org // Set pending exception and r0 to out of memory exception. 298359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org Label already_have_failure; 298459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org JumpIfOOM(masm, r0, ip, &already_have_failure); 298559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org Failure* out_of_memory = Failure::OutOfMemoryException(0x1); 298665a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); 298759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ bind(&already_have_failure); 298865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 298965a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org isolate))); 299065a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ str(r0, MemOperand(r2)); 299165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org // Fall through to the next label. 299265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 299365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&throw_termination_exception); 299465a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ ThrowUncatchable(r0); 299565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 299665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&throw_normal_exception); 299765a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ Throw(r0); 299865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 299965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 300065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 300165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 300265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: code entry 300365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: function 300465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: receiver 300565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: argc 300665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // [sp+0]: argv 300765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 300804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org Label invoke, handler_entry, exit; 300965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 30101510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 30111510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 301265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Called from C, so do not pop argc and args on exit (preserve sp) 301365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // No need to save register-passed args 301465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Save callee-saved registers (incl. cp and fp), sp, and lr 301565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ stm(db_w, sp, kCalleeSaved | lr.bit()); 301665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3017e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Save callee-saved vfp registers. 3018e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); 3019e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Set up the reserved register for 0.0. 3020e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vmov(kDoubleRegZero, 0.0); 3021e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ VFPEnsureFPSCRState(r4); 3022ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org 302365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get address of argv, see stm above. 302465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: code entry 302565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: function 302665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: receiver 302765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: argc 3028ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org 3029f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up argv in r4. 3030ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; 3031e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize; 3032ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org __ ldr(r4, MemOperand(sp, offset_to_argv)); 303365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 303465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Push a frame with special values setup to mark it as an entry frame. 303565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: code entry 303665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: function 303765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: receiver 303865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: argc 303965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r4: argv 3040ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Isolate* isolate = masm->isolate(); 304165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used. 304265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 304365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r7, Operand(Smi::FromInt(marker))); 304465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r6, Operand(Smi::FromInt(marker))); 3045ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ mov(r5, 304683e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate))); 304765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r5, MemOperand(r5)); 304865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Push(r8, r7, r6, r5); 304965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3050f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up frame pointer for the frame to be pushed. 305165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 305265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3053a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // If this is the outermost JS call, set js_entry_sp value. 3054c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org Label non_outermost_js; 305583e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate); 3056a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(r5, Operand(ExternalReference(js_entry_sp))); 3057a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ldr(r6, MemOperand(r5)); 3058ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ cmp(r6, Operand::Zero()); 3059c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ b(ne, &non_outermost_js); 3060c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ str(fp, MemOperand(r5)); 3061c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 3062c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org Label cont; 3063c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ b(&cont); 3064c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ bind(&non_outermost_js); 3065c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ mov(ip, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); 3066c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ bind(&cont); 3067c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ push(ip); 3068a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 306904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // Jump to a faked try block that does the invoke, with a faked catch 307004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // block that sets the pending exception. 307104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ jmp(&invoke); 30727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 30737028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // Block literal pool emission whilst taking the position of the handler 30747028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // entry. This avoids making the assumption that literal pools are always 30757028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // emitted after an instruction is emitted, rather than before. 30767028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org { 30777028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org Assembler::BlockConstPoolScope block_const_pool(masm); 30787028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org __ bind(&handler_entry); 30797028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org handler_offset_ = handler_entry.pos(); 30807028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // Caught exception: Store result (exception) in the pending exception 30817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // field in the JSEnv and return a failure sentinel. Coming in here the 30827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // fp will be invalid because the PushTryHandler below sets it to 0 to 30837028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // signal the existence of the JSEntry frame. 30847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 30857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org isolate))); 30867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org } 308765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r0, MemOperand(ip)); 308865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception()))); 308965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(&exit); 309065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 309104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // Invoke: Link this frame into the handler chain. There's only one 309204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // handler block in this code object, so its index is 0. 309365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&invoke); 309465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Must preserve r0-r4, r5-r7 are available. 309578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org __ PushTryHandler(StackHandler::JS_ENTRY, 0); 309665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If an exception not caught by another handler occurs, this handler 309765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // returns control to the code after the bl(&invoke) above, which 309865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // restores all kCalleeSaved registers (including cp and fp) to their 309965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // saved values before returning a failure to C. 310065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 310165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Clear any pending exceptions. 3102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(r5, Operand(isolate->factory()->the_hole_value())); 310383e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 3104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate))); 310565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r5, MemOperand(ip)); 310665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 310765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Invoke the function by calling through JS entry trampoline builtin. 310865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Notice that we cannot store a reference to the trampoline code directly in 310965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // this stub, because runtime stubs are not traversed when doing GC. 311065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 311165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Expected registers by Builtins::JSEntryTrampoline 311265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: code entry 311365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: function 311465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: receiver 311565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: argc 311665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r4: argv 311765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (is_construct) { 31187979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 3119ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate); 312065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(ip, Operand(construct_entry)); 312165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 31227979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org ExternalReference entry(Builtins::kJSEntryTrampoline, isolate); 312365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(ip, Operand(entry)); 312465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 312565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(ip, MemOperand(ip)); // deref address 312665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 312765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Branch and link to JSEntryTrampoline. We don't use the double underscore 312865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // macro for the add instruction because we don't want the coverage tool 31297028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // inserting instructions here after we read the pc. We block literal pool 31307028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // emission for the same reason. 31317028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org { 31327028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org Assembler::BlockConstPoolScope block_const_pool(masm); 31337028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org __ mov(lr, Operand(pc)); 31347028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org masm->add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 31357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org } 313665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3137c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org // Unlink this frame from the handler chain. 3138c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ PopTryHandler(); 313965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3140c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ bind(&exit); // r0 holds result 3141c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org // Check if the current stack frame is marked as the outermost JS frame. 3142c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org Label non_outermost_js_2; 3143c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ pop(r5); 3144c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 3145c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ b(ne, &non_outermost_js_2); 3146ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ mov(r6, Operand::Zero()); 3147a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(r5, Operand(ExternalReference(js_entry_sp))); 3148c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ str(r6, MemOperand(r5)); 3149c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org __ bind(&non_outermost_js_2); 315065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 315165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Restore the top frame descriptors from the stack. 315265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ pop(r3); 3153ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ mov(ip, 315483e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate))); 315565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(ip)); 315665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 315765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Reset the stack to the callee saved registers. 315865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 315965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 316065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Restore callee-saved registers and return. 316165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef DEBUG 316265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (FLAG_debug_code) { 316365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(lr, Operand(pc)); 316465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 316565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif 3166ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org 3167e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Restore callee-saved vfp registers. 3168e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); 3169ac2828d8d201b0631783404187688fbb786458a3lrn@chromium.org 317065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); 317165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 317265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 317365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 31740a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// Uses registers r0 to r4. 31750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// Expected input (depending on whether args are in registers or on the stack): 31760a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// * object: r0 or at sp + 1 * kPointerSize. 31770a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// * function: r1 or at sp. 31780a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// 31790a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// An inlined call site may have been generated before calling this stub. 31800a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// In this case the offset to the inline site to patch is passed on the stack, 31810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// in the safepoint slot for register r4. 31820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org// (See LCodeGen::DoInstanceOfKnownGlobal) 318365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid InstanceofStub::Generate(MacroAssembler* masm) { 31840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Call site inlining and patching implies arguments in registers. 31850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck()); 31860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // ReturnTrueFalse is only implemented for inlined call sites. 31870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); 31880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 3189023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // Fixed register usage throughout the stub: 31909e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org const Register object = r0; // Object (lhs). 31910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org Register map = r3; // Map of the object. 31929e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org const Register function = r1; // Function (rhs). 3193023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org const Register prototype = r4; // Prototype of the function. 31940a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org const Register inline_site = r9; 3195023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org const Register scratch = r2; 31960a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 3197f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com const int32_t kDeltaToLoadBoolResult = 4 * kPointerSize; 31980a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 3199023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org Label slow, loop, is_instance, is_not_instance, not_js_object; 32000a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 3201d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org if (!HasArgsInRegisters()) { 32029e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org __ ldr(object, MemOperand(sp, 1 * kPointerSize)); 32039e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org __ ldr(function, MemOperand(sp, 0)); 3204023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org } 320565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3206023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // Check that the left hand is a JS object and load map. 3207378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfSmi(object, ¬_js_object); 32089e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); 320965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 32100a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // If there is a call site cache don't look in the global cache, but do the 32110a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // real lookup and update the call site cache. 32120a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!HasCallSiteInlineCheck()) { 32130a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org Label miss; 3214fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 32150a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ b(ne, &miss); 3216fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); 32170a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ b(ne, &miss); 32180a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 32190a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 32200a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 32210a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ bind(&miss); 32220a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 322365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 32240a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Get the prototype of the function. 3225394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); 322665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 322765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the function prototype is a JS object. 3228378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfSmi(prototype, &slow); 3229023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 323065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 32310a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Update the global instanceof or call site inlined cache with the current 32320a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // map and function. The cached answer will be set when it is known below. 32330a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!HasCallSiteInlineCheck()) { 32340a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 32350a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 32360a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } else { 32370a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org ASSERT(HasArgsInRegisters()); 32380a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Patch the (relocated) inlined map check. 32390a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 32400a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // The offset was stored in r4 safepoint slot. 32410a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal) 32423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ LoadFromSafepointRegisterSlot(scratch, r4); 32430a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ sub(inline_site, lr, scratch); 32440a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Get the map location in scratch and patch it. 32450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ GetRelocatedValueLocation(inline_site, scratch); 3246f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com __ ldr(scratch, MemOperand(scratch)); 324741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org __ str(map, FieldMemOperand(scratch, Cell::kValueOffset)); 32480a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 324965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 325065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Register mapping: r3 is object map and r4 is function prototype. 325165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get prototype of object into r2. 3252023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset)); 325365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 32540a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // We don't need map any more. Use it as a scratch register. 32550a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org Register scratch2 = map; 32560a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org map = no_reg; 32570a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 325865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Loop through the prototype chain looking for the function prototype. 32590a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ LoadRoot(scratch2, Heap::kNullValueRootIndex); 326065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&loop); 3261023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ cmp(scratch, Operand(prototype)); 326265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &is_instance); 32630a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ cmp(scratch, scratch2); 326465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &is_not_instance); 3265023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); 3266023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); 326765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(&loop); 326865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 326965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&is_instance); 32700a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!HasCallSiteInlineCheck()) { 32710a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ mov(r0, Operand(Smi::FromInt(0))); 32720a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 32730a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } else { 32740a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Patch the call site to return true. 32750a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ LoadRoot(r0, Heap::kTrueValueRootIndex); 32760a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ add(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); 32770a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Get the boolean result location in scratch and patch it. 32780a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ GetRelocatedValueLocation(inline_site, scratch); 32790a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ str(r0, MemOperand(scratch)); 32800a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 32810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!ReturnTrueFalseObject()) { 32820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ mov(r0, Operand(Smi::FromInt(0))); 32830a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 32840a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 3285d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 328665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 328765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&is_not_instance); 32880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!HasCallSiteInlineCheck()) { 32890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ mov(r0, Operand(Smi::FromInt(1))); 32900a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 32910a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } else { 32920a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Patch the call site to return false. 32930a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ LoadRoot(r0, Heap::kFalseValueRootIndex); 32940a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ add(inline_site, inline_site, Operand(kDeltaToLoadBoolResult)); 32950a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org // Get the boolean result location in scratch and patch it. 32960a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ GetRelocatedValueLocation(inline_site, scratch); 32970a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ str(r0, MemOperand(scratch)); 32980a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 32990a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!ReturnTrueFalseObject()) { 33000a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ mov(r0, Operand(Smi::FromInt(1))); 33010a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 33020a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 3303d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 3304023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org 3305023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org Label object_not_null, object_not_null_or_smi; 3306023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ bind(¬_js_object); 3307023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // Before null, smi and string value checks, check that the rhs is a function 3308023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // as for a non-function rhs an exception needs to be thrown. 3309378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfSmi(function, &slow); 33100a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE); 3311023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ b(ne, &slow); 3312023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org 3313023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // Null is not instance of anything. 3314160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ cmp(scratch, Operand(masm->isolate()->factory()->null_value())); 3315023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ b(ne, &object_not_null); 3316023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ mov(r0, Operand(Smi::FromInt(1))); 3317d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 3318023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org 3319023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ bind(&object_not_null); 3320023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // Smi values are not instances of anything. 3321378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfNotSmi(object, &object_not_null_or_smi); 3322023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ mov(r0, Operand(Smi::FromInt(1))); 3323d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 3324023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org 3325023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ bind(&object_not_null_or_smi); 3326023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org // String values are not instances of anything. 3327023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ IsObjectJSStringType(object, scratch, &slow); 3328023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org __ mov(r0, Operand(Smi::FromInt(1))); 3329d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 333065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 333165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Slow-case. Tail call builtin. 3332d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ bind(&slow); 33330a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (!ReturnTrueFalseObject()) { 33340a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org if (HasArgsInRegisters()) { 33350a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ Push(r0, r1); 33360a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } 33378e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 33380a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org } else { 3339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 3340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 3341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Push(r0, r1); 3342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 3343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 3344ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ cmp(r0, Operand::Zero()); 33450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ LoadRoot(r0, Heap::kTrueValueRootIndex, eq); 33460a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ LoadRoot(r0, Heap::kFalseValueRootIndex, ne); 33470a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org __ Ret(HasArgsInRegisters() ? 0 : 2); 33489e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org } 334965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 335065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 335165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 33526bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) { 33536bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org Label miss; 33546bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org Register receiver; 33556bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org if (kind() == Code::KEYED_LOAD_IC) { 33566bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------- S t a t e ------------- 33576bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- lr : return address 33586bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r0 : key 33596bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r1 : receiver 33606bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------------------------------- 33614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(r0, Operand(masm->isolate()->factory()->prototype_string())); 33626bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org __ b(ne, &miss); 33636bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org receiver = r1; 33646bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org } else { 33656bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org ASSERT(kind() == Code::LOAD_IC); 33666bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------- S t a t e ------------- 33676bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r2 : name 33686bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- lr : return address 33696bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r0 : receiver 33706bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- sp[0] : receiver 33716bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------------------------------- 33726bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org receiver = r0; 33736bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org } 33746bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 33756bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss); 33766bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org __ bind(&miss); 3377bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org StubCompiler::TailCallBuiltin( 3378bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); 33796bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org} 33806bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 33816bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 33826bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgvoid StringLengthStub::Generate(MacroAssembler* masm) { 33836bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org Label miss; 33846bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org Register receiver; 33856bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org if (kind() == Code::KEYED_LOAD_IC) { 33866bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------- S t a t e ------------- 33876bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- lr : return address 33886bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r0 : key 33896bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r1 : receiver 33906bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------------------------------- 33914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(r0, Operand(masm->isolate()->factory()->length_string())); 33926bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org __ b(ne, &miss); 33936bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org receiver = r1; 33946bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org } else { 33956bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org ASSERT(kind() == Code::LOAD_IC); 33966bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------- S t a t e ------------- 33976bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r2 : name 33986bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- lr : return address 33996bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- r0 : receiver 34006bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // -- sp[0] : receiver 34016bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org // ----------------------------------- 34026bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org receiver = r0; 34036bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org } 34046bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 34056bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org StubCompiler::GenerateLoadStringLength(masm, receiver, r3, r4, &miss, 34066bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org support_wrapper_); 34076bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 34086bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org __ bind(&miss); 3409bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org StubCompiler::TailCallBuiltin( 3410bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); 34116bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org} 34126bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 34136bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org 3414d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.orgvoid StoreArrayLengthStub::Generate(MacroAssembler* masm) { 3415d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // This accepts as a receiver anything JSArray::SetElementsLength accepts 3416d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // (currently anything except for external arrays which means anything with 3417d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // elements of FixedArray type). Value must be a number, but only smis are 3418d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // accepted as the most common case. 3419d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org Label miss; 3420d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3421d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org Register receiver; 3422d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org Register value; 3423d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org if (kind() == Code::KEYED_STORE_IC) { 3424d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // ----------- S t a t e ------------- 3425d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- lr : return address 3426d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- r0 : value 3427d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- r1 : key 3428d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- r2 : receiver 3429d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // ----------------------------------- 34304a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(r1, Operand(masm->isolate()->factory()->length_string())); 3431d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ b(ne, &miss); 3432d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org receiver = r2; 3433d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org value = r0; 3434d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org } else { 3435d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org ASSERT(kind() == Code::STORE_IC); 3436d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // ----------- S t a t e ------------- 3437d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- lr : return address 3438d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- r0 : value 3439d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- r1 : receiver 3440d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // -- r2 : key 3441d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // ----------------------------------- 3442d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org receiver = r1; 3443d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org value = r0; 3444d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org } 3445d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org Register scratch = r3; 3446d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3447d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // Check that the receiver isn't a smi. 3448d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ JumpIfSmi(receiver, &miss); 3449d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3450d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // Check that the object is a JS array. 3451d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 3452d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ b(ne, &miss); 3453d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3454d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // Check that elements are FixedArray. 3455d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // We rely on StoreIC_ArrayLength below to deal with all types of 3456d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // fast elements (including COW). 3457d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset)); 3458d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE); 3459d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ b(ne, &miss); 3460d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3461d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // Check that the array has fast properties, otherwise the length 3462d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // property might have been redefined. 3463d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ ldr(scratch, FieldMemOperand(receiver, JSArray::kPropertiesOffset)); 3464d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ ldr(scratch, FieldMemOperand(scratch, FixedArray::kMapOffset)); 3465d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ CompareRoot(scratch, Heap::kHashTableMapRootIndex); 3466d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ b(eq, &miss); 3467d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3468d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // Check that value is a smi. 3469d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ JumpIfNotSmi(value, &miss); 3470d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3471d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org // Prepare tail call to StoreIC_ArrayLength. 3472d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ Push(receiver, value); 3473d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3474d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org ExternalReference ref = 3475d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate()); 3476d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ TailCallExternalReference(ref, 2, 1); 3477d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3478d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org __ bind(&miss); 3479d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3480bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org StubCompiler::TailCallBuiltin( 3481bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); 3482d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org} 3483d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 3484d16d8531698e91e9c60a7db9e0ba3c3bb15aff20mvstanton@chromium.org 34850a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgRegister InstanceofStub::left() { return r0; } 34860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 34870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 34880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgRegister InstanceofStub::right() { return r1; } 34890a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 34900a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org 349165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 349265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // The displacement is the offset of the last parameter (if any) 349365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // relative to the frame pointer. 34941456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kDisplacement = 349565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StandardFrameConstants::kCallerSPOffset - kPointerSize; 349665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 349765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the key is a smi. 349865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label slow; 3499378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfNotSmi(r1, &slow); 350065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 350165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check if the calling frame is an arguments adaptor frame. 350265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label adaptor; 350365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 350465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 350565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 350665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &adaptor); 350765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 350865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check index against formal parameters count limit passed in 350965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // through register r0. Use unsigned comparison to get negative 351065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // check for free. 351165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r1, r0); 3512d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org __ b(hs, &slow); 351365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 351465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Read the argument from the stack and return it. 351565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(r3, r0, r1); 3516bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r3, fp, Operand::PointerOffsetFromSmiKey(r3)); 351765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(r3, kDisplacement)); 351865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Jump(lr); 351965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 352065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Arguments adaptor case: Check index against actual arguments 352165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // limit found in the arguments adaptor frame. Use unsigned 352265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // comparison to get negative check for free. 352365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&adaptor); 352465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 352565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r1, r0); 352665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(cs, &slow); 352765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 352865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Read the argument from the adaptor frame and return it. 352965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(r3, r0, r1); 3530bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r3)); 353165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(r3, kDisplacement)); 353265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Jump(lr); 353365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 353465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Slow-case: Handle non-smi or out-of-bounds access to arguments 353565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // by calling the runtime system. 353665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&slow); 353765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ push(r1); 353865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 353965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 354065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 354165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 35427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { 354365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[0] : number of parameters 354465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[4] : receiver displacement 354565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[8] : function 354665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 354765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check if the calling frame is an arguments adaptor frame. 35487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Label runtime; 35497b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 35507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset)); 35517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 35527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ b(ne, &runtime); 35537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Patch the arguments.length and the parameters pointer in the current frame. 35557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 35567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r2, MemOperand(sp, 0 * kPointerSize)); 35577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r3, r3, Operand(r2, LSL, 1)); 35587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 35597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r3, MemOperand(sp, 1 * kPointerSize)); 35607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&runtime); 35627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 35637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org} 35647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { 35677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Stack layout: 35687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // sp[0] : number of parameters (tagged) 35697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // sp[4] : address of receiver argument 35707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // sp[8] : function 35717b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Registers used over whole function: 35727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r6 : allocated object (tagged) 35737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r9 : mapped parameter count (tagged) 35747b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35757b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 35767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r1 = parameter count (tagged) 35777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Check if the calling frame is an arguments adaptor frame. 35797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Label runtime; 35807b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Label adaptor_frame, try_allocate; 35817b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 35827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset)); 35837b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 35847b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ b(eq, &adaptor_frame); 35857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // No adaptor, parameter count = argument count. 35877b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r2, r1); 35887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ b(&try_allocate); 35897b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35907b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // We have an adaptor frame. Patch the parameters pointer. 35917b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&adaptor_frame); 35927b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 35937b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r3, r3, Operand(r2, LSL, 1)); 35947b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 35957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r3, MemOperand(sp, 1 * kPointerSize)); 35967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 35977b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r1 = parameter count (tagged) 35987b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r2 = argument count (tagged) 35997b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Compute the mapped parameter count = min(r1, r2) in r1. 36007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r1, Operand(r2)); 36017b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r1, Operand(r2), LeaveCC, gt); 36027b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&try_allocate); 36047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Compute the sizes of backing store, parameter map, and arguments object. 36067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // 1. Parameter map, has 2 extra words containing context and backing store. 36077b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org const int kParameterMapHeaderSize = 36087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org FixedArray::kHeaderSize + 2 * kPointerSize; 36097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // If there are no mapped parameters, we do not need the parameter_map. 36107b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r1, Operand(Smi::FromInt(0))); 3611ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ mov(r9, Operand::Zero(), LeaveCC, eq); 36127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne); 36137b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne); 36147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // 2. Backing store. 36167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(r2, LSL, 1)); 36177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(FixedArray::kHeaderSize)); 36187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // 3. Arguments object. 36207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(Heap::kArgumentsObjectSize)); 36217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36227b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Do the allocation of all three objects in one go. 3623f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT); 36247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r0 = address of new object(s) (tagged) 36267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r2 = argument count (tagged) 362746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Get the arguments boilerplate from the current native context into r4. 36287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org const int kNormalOffset = 36297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX); 36307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org const int kAliasedOffset = 36317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX); 36327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 363346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r4, MemOperand(r8, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 363446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); 3635ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ cmp(r1, Operand::Zero()); 36367b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r4, MemOperand(r4, kNormalOffset), eq); 36377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); 36387b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r0 = address of new object (tagged) 36407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r1 = mapped parameter count (tagged) 36417b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r2 = argument count (tagged) 36427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r4 = address of boilerplate object (tagged) 36437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Copy the JS object part. 36447b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { 36457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r3, FieldMemOperand(r4, i)); 36467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r3, FieldMemOperand(r0, i)); 36477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org } 36487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 3649f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up the callee in-object property. 36507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 36517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); 36527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org const int kCalleeOffset = JSObject::kHeaderSize + 36537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Heap::kArgumentsCalleeIndex * kPointerSize; 36547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r3, FieldMemOperand(r0, kCalleeOffset)); 36557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Use the length (smi tagged) and set that as an in-object property too. 36577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 36587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org const int kLengthOffset = JSObject::kHeaderSize + 36597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Heap::kArgumentsLengthIndex * kPointerSize; 36607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r2, FieldMemOperand(r0, kLengthOffset)); 36617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 3662f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up the elements pointer in the allocated arguments object. 36637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // If we allocated a parameter map, r4 will point there, otherwise 36647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // it will point to the backing store. 36657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r4, r0, Operand(Heap::kArgumentsObjectSize)); 36667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 36677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r0 = address of new object (tagged) 36697b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r1 = mapped parameter count (tagged) 36707b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r2 = argument count (tagged) 36717b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r4 = address of parameter map or backing store (tagged) 36727b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Initialize parameter map. If there are no mapped arguments, we're done. 36737b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Label skip_parameter_map; 36747b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r1, Operand(Smi::FromInt(0))); 36757b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Move backing store address to r3, because it is 36767b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // expected there when filling in the unmapped arguments. 36777b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r3, r4, LeaveCC, eq); 36787b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ b(eq, &skip_parameter_map); 36797b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36807b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ LoadRoot(r6, Heap::kNonStrictArgumentsElementsMapRootIndex); 36817b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset)); 36827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r6, r1, Operand(Smi::FromInt(2))); 36837b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset)); 36847b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r8, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize)); 36857b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r6, r4, Operand(r1, LSL, 1)); 36867b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r6, r6, Operand(kParameterMapHeaderSize)); 36877b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize)); 36887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 36897b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Copy the parameter slots and the holes in the arguments. 36907b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // We need to fill in mapped_parameter_count slots. They index the context, 36917b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // where parameters are stored in reverse order, at 36927b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 36937b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // The mapped parameter thus need to get indices 36947b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // MIN_CONTEXT_SLOTS+parameter_count-1 .. 36957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 36967b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // We loop from right to left. 36977b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Label parameters_loop, parameters_test; 36987b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r6, r1); 36997b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r9, MemOperand(sp, 0 * kPointerSize)); 37007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); 37017b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ sub(r9, r9, Operand(r1)); 37027b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ LoadRoot(r7, Heap::kTheHoleValueRootIndex); 37037b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r3, r4, Operand(r6, LSL, 1)); 37047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r3, r3, Operand(kParameterMapHeaderSize)); 37057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r6 = loop variable (tagged) 37077b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r1 = mapping index (tagged) 37087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r3 = address of backing store (tagged) 37097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r4 = address of parameter map (tagged) 37107b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r5 = temporary scratch (a.o., for address calculation) 37117b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r7 = the hole value 37127b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ jmp(¶meters_test); 37137b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(¶meters_loop); 37157b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ sub(r6, r6, Operand(Smi::FromInt(1))); 37167b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r5, Operand(r6, LSL, 1)); 37177b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r5, r5, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 37187b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r9, MemOperand(r4, r5)); 37197b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ sub(r5, r5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); 37207b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r7, MemOperand(r3, r5)); 37217b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(Smi::FromInt(1))); 37227b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(¶meters_test); 37237b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r6, Operand(Smi::FromInt(0))); 37247b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ b(ne, ¶meters_loop); 37257b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&skip_parameter_map); 37277b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r2 = argument count (tagged) 37287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r3 = address of backing store (tagged) 37297b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // r5 = scratch 37307b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Copy arguments header and remaining slots (if there are any). 37317b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex); 37327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset)); 37337b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset)); 37347b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37357b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Label arguments_loop, arguments_test; 37367b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ mov(r9, r1); 37377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r4, MemOperand(sp, 1 * kPointerSize)); 37387b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ sub(r4, r4, Operand(r9, LSL, 1)); 37397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ jmp(&arguments_test); 37407b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37417b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&arguments_loop); 37427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ sub(r4, r4, Operand(kPointerSize)); 37437b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r6, MemOperand(r4, 0)); 37447b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r5, r3, Operand(r9, LSL, 1)); 37457b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize)); 37467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r9, r9, Operand(Smi::FromInt(1))); 37477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&arguments_test); 37497b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ cmp(r9, Operand(r2)); 37507b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ b(lt, &arguments_loop); 37517b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37527b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Return and remove the on-stack parameters. 37537b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(sp, sp, Operand(3 * kPointerSize)); 37547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ Ret(); 37557b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Do the runtime call to allocate the arguments object. 3757f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // r2 = argument count (tagged) 37587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ bind(&runtime); 37597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. 37607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 37617b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org} 37627b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org 37647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.orgvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 37657b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // sp[0] : number of parameters 37667b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // sp[4] : receiver displacement 37677b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // sp[8] : function 37687b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org // Check if the calling frame is an arguments adaptor frame. 376965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label adaptor_frame, try_allocate, runtime; 377065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 377165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 377265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 377365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &adaptor_frame); 377465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 377565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the length from the frame. 377665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, MemOperand(sp, 0)); 377765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(&try_allocate); 377865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 377965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Patch the arguments.length and the parameters pointer. 378065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&adaptor_frame); 378165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 378265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, MemOperand(sp, 0)); 3783bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1)); 378465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 378565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(sp, 1 * kPointerSize)); 378665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 378765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Try the new space allocation. Start out with computing the size 378865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // of the arguments object and the elements array in words. 378965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label add_arguments_object; 379065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&try_allocate); 3791bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r1, SetCC); 379265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &add_arguments_object); 379365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); 379465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&add_arguments_object); 37957b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize)); 379665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 379765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Do the allocation of both objects in one go. 3798f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(r1, r0, r2, r3, &runtime, 3799f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 380065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 380146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Get the arguments boilerplate from the current native context. 380246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 380346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); 38047b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ ldr(r4, MemOperand(r4, Context::SlotOffset( 38057b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX))); 380665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 380765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Copy the JS object part. 3808fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org __ CopyFields(r0, r4, d0, JSObject::kHeaderSize / kPointerSize); 380965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 381065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the length (smi tagged) and set that as an in-object property too. 3811ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 381265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 3813ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + 38147b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org Heap::kArgumentsLengthIndex * kPointerSize)); 381565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 381665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If there are no actual arguments, we're done. 381765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label done; 381859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(r1, Operand::Zero()); 381965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &done); 382065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 382165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the parameters pointer from the stack. 382265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); 382365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 3824f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up the elements pointer in the allocated arguments object and 382565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // initialize the header in the elements fixed array. 38267b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict)); 382765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 382865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); 382965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); 383065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); 3831bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r1); 383265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 383365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Copy the fixed array slots. 383465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label loop; 3835f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up r4 to point to the first array slot. 383665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 383765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&loop); 383865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Pre-decrement r2 with kPointerSize on each iteration. 383965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Pre-decrement in order to skip receiver. 384065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); 384165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Post-increment r4 with kPointerSize on each iteration. 384265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); 384365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(r1, r1, Operand(1)); 384459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(r1, Operand::Zero()); 384565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &loop); 384665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 384765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Return and remove the on-stack parameters. 384865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&done); 384965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(3 * kPointerSize)); 385065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 385165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 385265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Do the runtime call to allocate the arguments object. 385365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&runtime); 38547b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); 385565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 385665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 385765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 385865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid RegExpExecStub::Generate(MacroAssembler* masm) { 385965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Just jump directly to runtime if native RegExp is not selected at compile 386065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // time or if regexp entry in generated code is turned off runtime switch or 386165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // at compilation. 386265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#ifdef V8_INTERPRETED_REGEXP 386365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 386465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#else // V8_INTERPRETED_REGEXP 386565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 386665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Stack frame on entry. 386765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[0]: last_match_info (expected JSArray) 386865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[4]: previous index 386965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[8]: subject string 387065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[12]: JSRegExp object 387165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 38721456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kLastMatchInfoOffset = 0 * kPointerSize; 38731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kPreviousIndexOffset = 1 * kPointerSize; 38741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kSubjectOffset = 2 * kPointerSize; 38751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kJSRegExpOffset = 3 * kPointerSize; 387665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 387771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org Label runtime; 387865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Allocation of registers for this function. These are in callee save 387965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // registers and will be preserved by the call to the native RegExp code, as 388065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // this code is called using the normal C calling convention. When calling 388165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // directly from generated code the native RegExp code will not do a GC and 388265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // therefore the content of these registers are safe to use after the call. 388365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register subject = r4; 388465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register regexp_data = r5; 388565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register last_match_info_elements = r6; 388665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 388765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Ensure that a RegExp stack is allocated. 3888ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Isolate* isolate = masm->isolate(); 388965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ExternalReference address_of_regexp_stack_memory_address = 3890ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExternalReference::address_of_regexp_stack_memory_address(isolate); 389165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ExternalReference address_of_regexp_stack_memory_size = 3892ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExternalReference::address_of_regexp_stack_memory_size(isolate); 389365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(address_of_regexp_stack_memory_size)); 389465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(r0, 0)); 389559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(r0, Operand::Zero()); 389665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &runtime); 389765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 389865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the first argument is a JSRegExp object. 389965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(sp, kJSRegExpOffset)); 39007b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(r0, &runtime); 390165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 390265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &runtime); 390365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 390465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the RegExp has been compiled (data contains a fixed array). 390565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset)); 390665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (FLAG_debug_code) { 3907bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTst(regexp_data); 3908594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected); 390965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE); 3910594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); 391165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 391265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 391365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // regexp_data: RegExp data (FixedArray) 391465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 391565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 391665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); 391765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &runtime); 391865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 391965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // regexp_data: RegExp data (FixedArray) 392065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the number of captures fit in the static offsets vector buffer. 392165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, 392265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 392371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Check (number_of_captures + 1) * 2 <= offsets vector size 392471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Or number_of_captures * 2 <= offsets vector size - 2 392571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Multiplying by 2 comes for free since r2 is smi-tagged. 392665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 392765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 392871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 392971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); 393065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(hi, &runtime); 393165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 39324668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // Reset offset for possibly sliced string. 393359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r9, Operand::Zero()); 393471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(subject, MemOperand(sp, kSubjectOffset)); 393571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ JumpIfSmi(subject, &runtime); 393671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ mov(r3, subject); // Make a copy of the original subject string. 393765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 393865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 393971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // subject: subject string 394071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // r3: subject string 394171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // r0: subject string instance type 394271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // regexp_data: RegExp data (FixedArray) 394371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Handle subject string according to its encoding and representation: 394471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (1) Sequential string? If yes, go to (5). 394571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (2) Anything but sequential or cons? If yes, go to (6). 394671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (3) Cons string. If the string is flat, replace subject with first string. 394771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Otherwise bailout. 394871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (4) Is subject external? If yes, go to (7). 394971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (5) Sequential string. Load regexp code according to encoding. 395071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (E) Carry on. 395171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org /// [...] 395271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 395371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Deferred code at the end of the stub: 395471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (6) Not a long external string? If yes, go to (8). 395571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (7) External string. Make it, offset-wise, look like a sequential string. 395671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Go to (5). 395771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (8) Short external string or not a string? If yes, bail out to runtime. 395871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (9) Sliced string. Replace subject with parent. Go to (4). 395971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 396071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org Label seq_string /* 5 */, external_string /* 7 */, 396171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org check_underlying /* 4 */, not_seq_nor_cons /* 6 */, 396271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org not_long_external /* 8 */; 396371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 396471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (1) Sequential string? If yes, go to (5). 39651b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ and_(r1, 39661b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org r0, 39671b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org Operand(kIsNotStringMask | 39681b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org kStringRepresentationMask | 39691b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org kShortExternalStringMask), 39701b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org SetCC); 397165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 397271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(eq, &seq_string); // Go to (5). 397365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 397471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (2) Anything but sequential or cons? If yes, go to (6). 397580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kConsStringTag < kExternalStringTag); 397680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 39771b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 39781b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 39794668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org __ cmp(r1, Operand(kExternalStringTag)); 398071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(ge, ¬_seq_nor_cons); // Go to (6). 39811b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org 398271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (3) Cons string. Check that it's flat. 398371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Replace subject with first string and reload instance type. 398465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); 39854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ CompareRoot(r0, Heap::kempty_stringRootIndex); 398665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &runtime); 398765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 398871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 398971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (4) Is subject external? If yes, go to (7). 399071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ bind(&check_underlying); 399165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 399265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 399365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 399465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r0, Operand(kStringRepresentationMask)); 399571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // The underlying external string is never a short external string. 399671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org STATIC_CHECK(ExternalString::kMaxShortLength < ConsString::kMinLength); 399771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org STATIC_CHECK(ExternalString::kMaxShortLength < SlicedString::kMinLength); 399871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(ne, &external_string); // Go to (7). 39991b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org 400071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (5) Sequential string. Load regexp code according to encoding. 400165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&seq_string); 400271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // subject: sequential subject string (or look-alike, external string) 400371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // r3: original subject string 400471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Load previous index and check range before r3 is overwritten. We have to 400571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // use r3 instead of subject here because subject might have been only made 400671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // to look like a sequential string when it actually is an external string. 400771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); 400871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ JumpIfNotSmi(r1, &runtime); 400971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset)); 401071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ cmp(r3, Operand(r1)); 401171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(ls, &runtime); 4012bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r1); 401371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 4014e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org STATIC_ASSERT(4 == kOneByteStringTag); 401565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kTwoByteStringTag == 0); 401665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(r0, r0, Operand(kStringEncodingMask)); 401765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r3, Operand(r0, ASR, 2), SetCC); 401865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); 401965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); 402065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 402171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (E) Carry on. String handling is done. 402271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // r7: irregexp code 402365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the irregexp code has been generated for the actual string 402465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // encoding. If it has, the field contains a code object otherwise it contains 4025ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org // a smi (code flushing support). 4026ddda9e81d3175130f2029c0e1205d265a00c32edjkummerow@chromium.org __ JumpIfSmi(r7, &runtime); 402765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 402865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: previous index 4029badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // r3: encoding of subject string (1 if ASCII, 0 if two_byte); 403065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r7: code 403165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // subject: Subject string 403265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // regexp_data: RegExp data (FixedArray) 403365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // All checks done. Now push arguments for native regexp code. 40347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); 403565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4036ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org // Isolates: note we add an additional parameter here (isolate pointer). 403715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org const int kRegExpExecuteArguments = 9; 40381456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kParameterRegisters = 4; 403949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 404049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 404149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Stack pointer now points to cell where return address is to be written. 404249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Arguments are before that on the stack or in registers. 404365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 404415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // Argument 9 (sp[20]): Pass current isolate address. 404532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ mov(r0, Operand(ExternalReference::isolate_address(isolate))); 404615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org __ str(r0, MemOperand(sp, 5 * kPointerSize)); 4047ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 404815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript. 404965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(1)); 405015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org __ str(r0, MemOperand(sp, 4 * kPointerSize)); 405165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 405215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area. 405365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(address_of_regexp_stack_memory_address)); 405465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(r0, 0)); 405565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r2, Operand(address_of_regexp_stack_memory_size)); 405665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, MemOperand(r2, 0)); 405765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r0, r0, Operand(r2)); 405815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org __ str(r0, MemOperand(sp, 3 * kPointerSize)); 405915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org 406015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // Argument 6: Set the number of capture registers to zero to force global 406115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // regexps to behave as non-global. This does not affect non-global regexps. 406259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r0, Operand::Zero()); 406349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ str(r0, MemOperand(sp, 2 * kPointerSize)); 406465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 406549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Argument 5 (sp[4]): static offsets vector buffer. 4066ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ mov(r0, 4067ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Operand(ExternalReference::address_of_static_offsets_vector(isolate))); 406849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ str(r0, MemOperand(sp, 1 * kPointerSize)); 406965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 407065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // For arguments 4 and 3 get string length, calculate start of string data and 407165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // calculate the shift of the index (0 for ASCII and 1 for two byte). 4072c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(r8, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 407365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ eor(r3, r3, Operand(1)); 40744668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // Load the length from the original subject string from the previous stack 40754668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // frame. Therefore we have to use fp, which points exactly to two pointer 40764668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // sizes below the previous sp. (Because creating a new stack frame pushes 40774668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) 40781805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); 40794668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // If slice offset is not 0, load the length from the original sliced string. 40804668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // Argument 4, r3: End of string data 40814668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // Argument 3, r2: Start of string data 40824668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org // Prepare start and end index of the input. 40834668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org __ add(r9, r8, Operand(r9, LSL, r3)); 408465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r2, r9, Operand(r1, LSL, r3)); 40854668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org 40861805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ ldr(r8, FieldMemOperand(subject, String::kLengthOffset)); 4087bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r8); 40884668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org __ add(r3, r9, Operand(r8, LSL, r3)); 408965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 409065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Argument 2 (r1): Previous index. 409165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Already there 409265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 409365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Argument 1 (r0): Subject string. 40941805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ mov(r0, subject); 409565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 409665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Locate the code entry and call it. 409765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); 409849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org DirectCEntryStub stub; 409949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org stub.GenerateCall(masm, r7); 410049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 410149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ LeaveExitFrame(false, no_reg); 410265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 410365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: result 410465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // subject: subject string (callee saved) 410565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // regexp_data: RegExp data (callee saved) 410665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // last_match_info_elements: Last match info elements (callee saved) 410765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check the result. 410865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label success; 410915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org __ cmp(r0, Operand(1)); 411015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // We expect exactly one result since we force the called regexp to behave 411115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org // as non-global. 411265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &success); 411365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label failure; 41141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); 411565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &failure); 41161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 411765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If not exception it can only be retry. Handle that in the runtime system. 411865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &runtime); 411965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Result must now be exception. If there is no pending exception already a 412065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // stack overflow (on the backtrack stack) was detected in RegExp code but 412165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // haven't created the exception yet. Handle that in the runtime system. 412265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // TODO(592): Rerunning the RegExp to get the stack overflow exception. 4123c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(r1, Operand(isolate->factory()->the_hole_value())); 412483e168294456ca2f02db421a635f7d5f5d023966kmillikin@chromium.org __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 4125ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate))); 412649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ ldr(r0, MemOperand(r2, 0)); 41271805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ cmp(r0, r1); 412865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &runtime); 412949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 413049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ str(r1, MemOperand(r2, 0)); // Clear pending exception. 413149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 413249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Check if the exception is a termination. If so, throw as uncatchable. 41331805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex); 41341805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 413549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org Label termination_exception; 413649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ b(eq, &termination_exception); 413749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 413865a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ Throw(r0); 413949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 414049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ bind(&termination_exception); 414165a89c29ac6da09f5726f48f68eae9587b0e562aulan@chromium.org __ ThrowUncatchable(r0); 414249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 414365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&failure); 414465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // For failure and exception return null. 4145160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ mov(r0, Operand(masm->isolate()->factory()->null_value())); 414665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(4 * kPointerSize)); 414765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 414865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 414965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Process the result from the native regexp code. 415065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&success); 415165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, 415265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 415365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Calculate number of capture registers (number_of_captures + 1) * 2. 415471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Multiplying by 2 comes for free since r1 is smi-tagged. 415565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 415665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 415765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r1, r1, Operand(2)); // r1 was a smi. 415865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 415971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); 416071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ JumpIfSmi(r0, &runtime); 416171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ CompareObjectType(r0, r2, r2, JS_ARRAY_TYPE); 416271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(ne, &runtime); 416371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Check that the JSArray is in fast case. 416471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(last_match_info_elements, 416571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org FieldMemOperand(r0, JSArray::kElementsOffset)); 416671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 416771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex); 416871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(ne, &runtime); 416971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Check that the last match info has space for the capture registers and the 417071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // additional information. 417171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(r0, 417271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 417371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ add(r2, r1, Operand(RegExpImpl::kLastMatchOverhead)); 4174bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ cmp(r2, Operand::SmiUntag(r0)); 417571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(gt, &runtime); 417671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 417765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: number of capture registers 417865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r4: subject string 417965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Store the capture count. 4180bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTag(r2, r1); 418165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r2, FieldMemOperand(last_match_info_elements, 418265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org RegExpImpl::kLastCaptureCountOffset)); 418365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Store last subject and last input. 418465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(subject, 418565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org FieldMemOperand(last_match_info_elements, 418665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org RegExpImpl::kLastSubjectOffset)); 4187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(r2, subject); 4188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ RecordWriteField(last_match_info_elements, 4189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RegExpImpl::kLastSubjectOffset, 419071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org subject, 4191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com r7, 4192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com kLRHasNotBeenSaved, 4193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com kDontSaveFPRegs); 419471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ mov(subject, r2); 419565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(subject, 419665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org FieldMemOperand(last_match_info_elements, 419765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org RegExpImpl::kLastInputOffset)); 4198c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ RecordWriteField(last_match_info_elements, 4199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RegExpImpl::kLastInputOffset, 4200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com subject, 4201c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com r7, 4202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com kLRHasNotBeenSaved, 4203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com kDontSaveFPRegs); 420465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 420565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the static offsets vector filled by the native regexp code. 420665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ExternalReference address_of_static_offsets_vector = 4207ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExternalReference::address_of_static_offsets_vector(isolate); 420865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r2, Operand(address_of_static_offsets_vector)); 420965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 421065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: number of capture registers 421165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: offsets vector 421265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label next_capture, done; 421365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Capture register counter starts from number of capture registers and 421465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // counts down until wraping after zero. 421565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r0, 421665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org last_match_info_elements, 421765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); 421865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&next_capture); 421965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(r1, r1, Operand(1), SetCC); 422065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(mi, &done); 422165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Read the value from the static offsets vector buffer. 422265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex)); 422365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Store the smi value in the last match info. 4224bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTag(r3); 422565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); 422665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(&next_capture); 422765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&done); 422865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 422965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Return last match info. 423065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); 423165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(4 * kPointerSize)); 423265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 423365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 423471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Do the runtime call to execute the regexp. 423571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ bind(&runtime); 423671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 423771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 423871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Deferred code for string handling. 423971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (6) Not a long external string? If yes, go to (8). 424071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ bind(¬_seq_nor_cons); 424171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Compare flags are still set. 424271fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(gt, ¬_long_external); // Go to (8). 424371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 424471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (7) External string. Make it, offset-wise, look like a sequential string. 42451b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ bind(&external_string); 42461b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 42471b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 42481b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org if (FLAG_debug_code) { 42491b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org // Assert that we do not have a cons or slice (indirect strings) here. 42501b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org // Sequential strings have already been ruled out. 42511b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ tst(r0, Operand(kIsIndirectStringMask)); 4252594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kExternalStringExpectedButNotFound); 42531b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org } 42541b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ ldr(subject, 42551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 42561b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org // Move the pointer so that offset-wise, it looks like a sequential string. 4257fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 42581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org __ sub(subject, 42591b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org subject, 42601b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 426171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ jmp(&seq_string); // Go to (5). 42621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org 426371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (8) Short external string or not a string? If yes, bail out to runtime. 426471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ bind(¬_long_external); 426571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 426671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask)); 426771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ b(ne, &runtime); 426871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org 426971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // (9) Sliced string. Replace subject with parent. Go to (4). 427071fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org // Load offset into r9 and replace subject string with parent. 427171fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 4272bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r9); 427371fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 427471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org __ jmp(&check_underlying); // Go to (4). 427565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif // V8_INTERPRETED_REGEXP 427665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 427765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 427865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4279a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid RegExpConstructResultStub::Generate(MacroAssembler* masm) { 4280a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org const int kMaxInlineLength = 100; 4281a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label slowcase; 4282a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label done; 4283160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org Factory* factory = masm->isolate()->factory(); 4284160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org 4285a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ldr(r1, MemOperand(sp, kPointerSize * 2)); 4286a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org STATIC_ASSERT(kSmiTag == 0); 4287a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org STATIC_ASSERT(kSmiTagSize == 1); 42887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfNotSmi(r1, &slowcase); 4289a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ cmp(r1, Operand(Smi::FromInt(kMaxInlineLength))); 4290a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ b(hi, &slowcase); 4291a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Smi-tagging is equivalent to multiplying by 2. 4292a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Allocate RegExpResult followed by FixedArray with size in ebx. 4293a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // JSArray: [Map][empty properties][Elements][Length-smi][index][input] 4294a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Elements: [Map][Length][..elements..] 4295a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Size of JSArray with two in-object properties and the header of a 4296a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // FixedArray. 4297a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org int objects_size = 4298a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize; 4299bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r5, r1); 4300a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ add(r2, r5, Operand(objects_size)); 4301f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate( 4302a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org r2, // In: Size, in words. 4303a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org r0, // Out: Start of allocation (tagged). 4304a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org r3, // Scratch register. 4305a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org r4, // Scratch register. 4306a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org &slowcase, 4307a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 4308a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r0: Start of allocated area, object-tagged. 4309a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r1: Number of elements in array, as smi. 4310a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r5: Number of elements, untagged. 4311a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4312a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Set JSArray map to global.regexp_result_map(). 4313a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Set empty properties FixedArray. 4314a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Set elements to point to FixedArray allocated right after the JSArray. 4315a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Interleave operations for better latency. 431646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 4317a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ add(r3, r0, Operand(JSRegExpResult::kSize)); 4318160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ mov(r4, Operand(factory->empty_fixed_array())); 431946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset)); 4320a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); 4321a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX)); 4322a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 4323a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 4324a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4325a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Set input, index and length fields from arguments. 4326a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ldr(r1, MemOperand(sp, kPointerSize * 0)); 4327fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ ldr(r2, MemOperand(sp, kPointerSize * 1)); 4328fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ ldr(r6, MemOperand(sp, kPointerSize * 2)); 4329a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r1, FieldMemOperand(r0, JSRegExpResult::kInputOffset)); 4330fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ str(r2, FieldMemOperand(r0, JSRegExpResult::kIndexOffset)); 4331fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ str(r6, FieldMemOperand(r0, JSArray::kLengthOffset)); 4332a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4333a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Fill out the elements FixedArray. 4334a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r0: JSArray, tagged. 4335a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r3: FixedArray, tagged. 4336a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r5: Number of elements in array, untagged. 4337a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4338a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Set map. 4339160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org __ mov(r2, Operand(factory->fixed_array_map())); 4340a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 4341a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Set FixedArray length. 4342bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTag(r6, r5); 4343a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r6, FieldMemOperand(r3, FixedArray::kLengthOffset)); 434456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org // Fill contents of fixed-array with undefined. 434556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 4346a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 434756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org // Fill fixed array elements with undefined. 4348a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r0: JSArray, tagged. 434956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org // r2: undefined. 4350a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r3: Start of elements in FixedArray. 4351a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // r5: Number of elements to fill. 4352a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label loop; 435359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(r5, Operand::Zero()); 4354a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&loop); 4355fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ b(le, &done); // Jump if r5 is negative or zero. 4356a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ sub(r5, r5, Operand(1), SetCC); 4357a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ str(r2, MemOperand(r3, r5, LSL, kPointerSizeLog2)); 4358a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ jmp(&loop); 4359a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4360a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&done); 4361a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ add(sp, sp, Operand(3 * kPointerSize)); 4362a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ Ret(); 4363a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4364a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&slowcase); 4365a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); 4366a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 4367a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 4368a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 43694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgstatic void GenerateRecordCallTarget(MacroAssembler* masm) { 43704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Cache the called function in a global property cell. Cache states 43714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // are uninitialized, monomorphic (indicated by a JSFunction), and 43724a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // megamorphic. 43734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // r1 : the function to call 43744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // r2 : cache cell for call target 43754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Label initialize, done, miss, megamorphic, not_array_function; 43764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 43774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), 43784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org masm->isolate()->heap()->undefined_value()); 43794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), 43804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org masm->isolate()->heap()->the_hole_value()); 43814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 43824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Load the cache state into r3. 438341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); 43844a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 43854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // A monomorphic cache hit or an already megamorphic state: invoke the 43864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // function without changing the state. 43874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(r3, r1); 43884a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ b(eq, &done); 43894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 4390bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // If we came here, we need to see if we are the array function. 4391bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // If we didn't have a matching function, and we didn't find the megamorph 4392bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // sentinel, then we have in the cell either some other function or an 4393bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // AllocationSite. Do a map check on the object in ecx. 4394bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org Handle<Map> allocation_site_map( 4395bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org masm->isolate()->heap()->allocation_site_map(), 4396bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org masm->isolate()); 4397bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ ldr(r5, FieldMemOperand(r3, 0)); 4398bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); 4399bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ b(ne, &miss); 44001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 44014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Make sure the function is the Array() function 44024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ LoadArrayFunction(r3); 44034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(r1, r3); 44044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ b(ne, &megamorphic); 44054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ jmp(&done); 44064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 44074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&miss); 44084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 44094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // A monomorphic miss (i.e, here the cache is not uninitialized) goes 44104a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // megamorphic. 44114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); 44124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ b(eq, &initialize); 44134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // MegamorphicSentinel is an immortal immovable object (undefined) so no 44144a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // write-barrier is needed. 44154a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&megamorphic); 44164a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 441741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org __ str(ip, FieldMemOperand(r2, Cell::kValueOffset)); 44184e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ jmp(&done); 44194a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 44204a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // An uninitialized cache is patched with the function or sentinel to 44214a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // indicate the ElementsKind if function is the Array constructor. 44224a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&initialize); 44234a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Make sure the function is the Array() function 44244a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ LoadArrayFunction(r3); 44254a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(r1, r3); 44264a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ b(ne, ¬_array_function); 44274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 4428bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // The target function is the Array constructor, 4429bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Create an AllocationSite if we don't already have it, store it in the cell 4430bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org { 4431bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 4432bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 443367233eb8592c3336a5489ddca147878265df3ab7jkummerow@chromium.org __ SmiTag(r0); 4434bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ push(r0); 4435bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ push(r1); 4436bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ push(r2); 4437bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 4438bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org CreateAllocationSiteStub create_stub; 4439bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CallStub(&create_stub); 4440bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 4441bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ pop(r2); 4442bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ pop(r1); 4443bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ pop(r0); 444467233eb8592c3336a5489ddca147878265df3ab7jkummerow@chromium.org __ SmiUntag(r0); 4445bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 44464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ b(&done); 44474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 44484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(¬_array_function); 444941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org __ str(r1, FieldMemOperand(r2, Cell::kValueOffset)); 44504a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // No need for a write barrier here - cells are rescanned. 44514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 44524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&done); 44534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org} 44544a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 44554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 445665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid CallFunctionStub::Generate(MacroAssembler* masm) { 4457c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org // r1 : the function to call 4458fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r2 : cache cell for call target 445934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org Label slow, non_function; 446065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 446140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // The receiver might implicitly be the global object. This is 446240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // indicated by passing the hole as the receiver to the call 446340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // function stub. 446440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org if (ReceiverMightBeImplicit()) { 446540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org Label call; 446665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the receiver from the stack. 446765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // function, receiver [, arguments] 446840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ ldr(r4, MemOperand(sp, argc_ * kPointerSize)); 446940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Call as function is indicated with the hole. 447040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); 447140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ b(ne, &call); 447240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Patch the receiver on the stack with the global receiver object. 447346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ ldr(r3, 447446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 447588d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org __ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalReceiverOffset)); 447688d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org __ str(r3, MemOperand(sp, argc_ * kPointerSize)); 447740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ bind(&call); 447865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 447965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 448065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that the function is really a JavaScript function. 448165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: pushed function (to be verified) 448234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ JumpIfSmi(r1, &non_function); 448365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the map of the function object. 448488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 448565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &slow); 448665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 448788d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org if (RecordCallTarget()) { 44881510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org GenerateRecordCallTarget(masm); 448988d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org } 449088d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org 449165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Fast-case: Invoke the function now. 449265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: pushed function 449365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ParameterCount actual(argc_); 449440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org 449540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org if (ReceiverMightBeImplicit()) { 449640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org Label call_as_function; 449740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); 449840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ b(eq, &call_as_function); 4499d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ InvokeFunction(r1, 4500d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org actual, 4501d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org JUMP_FUNCTION, 4502d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org NullCallWrapper(), 4503d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org CALL_AS_METHOD); 450440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ bind(&call_as_function); 450540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org } 450640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ InvokeFunction(r1, 450740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org actual, 450840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org JUMP_FUNCTION, 450940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org NullCallWrapper(), 451040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org CALL_AS_FUNCTION); 451165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 451265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Slow-case: Non-function called. 451365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&slow); 451488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org if (RecordCallTarget()) { 451588d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org // If there is a call target cache, mark it megamorphic in the 451688d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org // non-function case. MegamorphicSentinel is an immortal immovable 451788d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org // object (undefined) so no write barrier is needed. 451888d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), 451988d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org masm->isolate()->heap()->undefined_value()); 452088d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 452141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org __ str(ip, FieldMemOperand(r2, Cell::kValueOffset)); 452288d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org } 452334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // Check for function proxy. 452488d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); 452534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ b(ne, &non_function); 452634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ push(r1); // put proxy as additional argument 452759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32)); 452859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r2, Operand::Zero()); 452934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); 4530c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ SetCallKind(r5, CALL_AS_METHOD); 453134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org { 453234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org Handle<Code> adaptor = 453334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 453434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ Jump(adaptor, RelocInfo::CODE_TARGET); 453534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org } 453634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 453765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 453865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // of the original receiver from the call site). 453934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&non_function); 454065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, MemOperand(sp, argc_ * kPointerSize)); 4541f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com __ mov(r0, Operand(argc_)); // Set up the number of arguments. 454259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r2, Operand::Zero()); 454365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 4544717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org __ SetCallKind(r5, CALL_AS_METHOD); 45457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 454665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org RelocInfo::CODE_TARGET); 454765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 454865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 454965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4550fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgvoid CallConstructStub::Generate(MacroAssembler* masm) { 4551fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r0 : number of arguments 4552fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r1 : the function to call 4553fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r2 : cache cell for call target 4554fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org Label slow, non_function_call; 4555fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 4556fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Check that the function is not a smi. 4557fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ JumpIfSmi(r1, &non_function_call); 4558fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Check that the function is a JSFunction. 4559fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 4560fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ b(ne, &slow); 4561fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 4562fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org if (RecordCallTarget()) { 45631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org GenerateRecordCallTarget(masm); 4564fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org } 4565fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 4566fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Jump to the function-specific construct stub. 45671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Register jmp_reg = r3; 45684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 45694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldr(jmp_reg, FieldMemOperand(jmp_reg, 45704a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org SharedFunctionInfo::kConstructStubOffset)); 45714a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); 4572fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 4573fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r0: number of arguments 4574fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r1: called object 4575fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // r3: object type 4576fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org Label do_call; 4577fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ bind(&slow); 4578fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); 4579fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ b(ne, &non_function_call); 4580fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 4581fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ jmp(&do_call); 4582fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 4583fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ bind(&non_function_call); 4584fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 4585fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ bind(&do_call); 4586fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Set expected number of arguments to zero (not changing r0). 458759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ mov(r2, Operand::Zero()); 4588fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ SetCallKind(r5, CALL_AS_METHOD); 4589fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 4590fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org RelocInfo::CODE_TARGET); 4591fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org} 4592fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 4593fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org 459465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// StringCharCodeAtGenerator 459565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 459665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label flat_string; 459765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label ascii_string; 459865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label got_char_code; 45994668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org Label sliced_string; 460065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 460165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If the receiver is a smi trigger the non-string case. 4602378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfSmi(object_, receiver_not_string_); 460365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 460465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Fetch the instance type of the receiver into result register. 460565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 460665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 460765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If the receiver is not a string trigger the non-string case. 460865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(result_, Operand(kIsNotStringMask)); 460965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, receiver_not_string_); 461065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 461165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If the index is non-smi trigger the non-smi case. 4612378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ JumpIfNotSmi(index_, &index_not_smi_); 461365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&got_smi_index_); 461465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 461565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check for index out of range. 461665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); 4617c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ cmp(ip, Operand(index_)); 461865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ls, index_out_of_range_); 461965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4620bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(index_); 46211b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org 46221b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org StringCharLoadGenerator::Generate(masm, 46231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org object_, 46241b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org index_, 46251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org result_, 46261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org &call_runtime_); 462765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4628bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTag(result_); 462965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&exit_); 463065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 463165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 463265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 463365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharCodeAtGenerator::GenerateSlow( 4634c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org MacroAssembler* masm, 4635c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org const RuntimeCallHelper& call_helper) { 4636594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 463765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 463865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Index is not a smi. 463965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&index_not_smi_); 464065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If index is a heap number, try converting it to an integer. 464165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CheckMap(index_, 4642c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org result_, 464365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Heap::kHeapNumberMapRootIndex, 464465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org index_not_number_, 4645c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org DONT_DO_SMI_CHECK); 464665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org call_helper.BeforeCall(masm); 4647c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ push(object_); 464865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ push(index_); // Consumed by runtime conversion function. 464965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (index_flags_ == STRING_INDEX_IS_NUMBER) { 465065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 465165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 465265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 465365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // NumberToSmi discards numbers that are not exact integers. 465465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CallRuntime(Runtime::kNumberToSmi, 1); 465565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 465665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Save the conversion result before the pop instructions below 465765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // have a chance to overwrite it. 4658c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ Move(index_, r0); 465965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ pop(object_); 466065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Reload the instance type. 466165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 466265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 466365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org call_helper.AfterCall(masm); 466465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If index is still not a smi, it must be out of range. 4665c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ JumpIfNotSmi(index_, index_out_of_range_); 466665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Otherwise, return to the fast path. 466765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(&got_smi_index_); 466865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 466965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Call runtime. We get here when the receiver is a string and the 467065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // index is a number, but the code of getting the actual character 467165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // is too complex (e.g., when the string needs to be flattened). 467265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&call_runtime_); 467365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org call_helper.BeforeCall(masm); 4674bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTag(index_); 467565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Push(object_, index_); 467665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CallRuntime(Runtime::kStringCharCodeAt, 2); 467765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Move(result_, r0); 467865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org call_helper.AfterCall(masm); 467965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(&exit_); 468065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4681594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 468265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 468365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 468465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 468565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// ------------------------------------------------------------------------- 468665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org// StringCharFromCodeGenerator 468765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 468865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 468965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Fast case of Heap::LookupSingleCharacterStringFromCode. 469065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 469165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiShiftSize == 0); 469259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1)); 469365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(code_, 469465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Operand(kSmiTagMask | 469559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org ((~String::kMaxOneByteCharCode) << kSmiTagSize))); 4696378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org __ b(ne, &slow_case_); 469765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 469865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 4699badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // At this point code register contains smi tagged ASCII char code. 4700bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(result_, result_, Operand::PointerOffsetFromSmiKey(code_)); 470165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); 4702fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); 470365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &slow_case_); 470465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&exit_); 470565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 470665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 470765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 470865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCharFromCodeGenerator::GenerateSlow( 4709c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org MacroAssembler* masm, 4710c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org const RuntimeCallHelper& call_helper) { 4711594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 471265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 471365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&slow_case_); 471465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org call_helper.BeforeCall(masm); 471565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ push(code_); 471665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ CallRuntime(Runtime::kCharFromCode, 1); 471765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Move(result_, r0); 471865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org call_helper.AfterCall(masm); 471965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(&exit_); 472065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 4721594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 472265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 472365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 472465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 472565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 472665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register dest, 472765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register src, 472865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register count, 472965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch, 473065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org bool ascii) { 473165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label loop; 473265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label done; 473365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // This loop just copies one character at a time, as it is only used for very 473465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // short strings. 473565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (!ascii) { 473665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(count, count, Operand(count), SetCC); 473765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 473859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(count, Operand::Zero()); 473965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 474065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &done); 474165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 474265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&loop); 474365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(scratch, MemOperand(src, 1, PostIndex)); 474465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Perform sub between load and dependent store to get the load time to 474565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // complete. 474665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(count, count, Operand(1), SetCC); 474765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch, MemOperand(dest, 1, PostIndex)); 474865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // last iteration. 474965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(gt, &loop); 475065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 475165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&done); 475265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 475365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 475465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 475565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgenum CopyCharactersFlags { 475665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org COPY_ASCII = 1, 475765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org DEST_ALWAYS_ALIGNED = 2 475865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}; 475965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 476065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 476165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, 476265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register dest, 476365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register src, 476465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register count, 476565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch1, 476665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch2, 476765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch3, 476865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch4, 476965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch5, 477065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org int flags) { 477165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org bool ascii = (flags & COPY_ASCII) != 0; 477265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; 477365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 477465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (dest_always_aligned && FLAG_debug_code) { 477565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check that destination is actually word aligned if the flag says 477665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // that it is. 477765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(dest, Operand(kPointerAlignmentMask)); 4778594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Check(eq, kDestinationOfCopyNotAligned); 477965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 478065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 478165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org const int kReadAlignment = 4; 478265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org const int kReadAlignmentMask = kReadAlignment - 1; 478365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Ensure that reading an entire aligned word containing the last character 478465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // of a string will not read outside the allocated area (because we pad up 478565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // to kObjectAlignment). 478665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kObjectAlignment >= kReadAlignment); 478765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Assumes word reads and writes are little endian. 478865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Nothing to do for zero characters. 478965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label done; 479065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (!ascii) { 479165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(count, count, Operand(count), SetCC); 479265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 479359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(count, Operand::Zero()); 479465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 479565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &done); 479665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 479765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Assume that you cannot read (or write) unaligned. 479865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label byte_loop; 479965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Must copy at least eight bytes, otherwise just do it one byte at a time. 480065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(count, Operand(8)); 480165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(count, dest, Operand(count)); 480265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register limit = count; // Read until src equals this. 480365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(lt, &byte_loop); 480465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 480565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (!dest_always_aligned) { 480665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Align dest by byte copying. Copies between zero and three bytes. 480765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(scratch4, dest, Operand(kReadAlignmentMask), SetCC); 480865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label dest_aligned; 480965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &dest_aligned); 481065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch4, Operand(2)); 481165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(scratch1, MemOperand(src, 1, PostIndex)); 481265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(scratch2, MemOperand(src, 1, PostIndex), le); 481365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(scratch3, MemOperand(src, 1, PostIndex), lt); 481465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 481565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch2, MemOperand(dest, 1, PostIndex), le); 481665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch3, MemOperand(dest, 1, PostIndex), lt); 481765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&dest_aligned); 481865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 481965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 482065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label simple_loop; 482165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 482265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch4, dest, Operand(src)); 482365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(scratch4, scratch4, Operand(0x03), SetCC); 482465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &simple_loop); 482565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Shift register is number of bits in a source word that 482665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // must be combined with bits in the next source word in order 482765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // to create a destination word. 482865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 482965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Complex loop for src/dst that are not aligned the same way. 483065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org { 483165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label loop; 483265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch4, Operand(scratch4, LSL, 3)); 483365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register left_shift = scratch4; 483465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(src, src, Operand(~3)); // Round down to load previous word. 483565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(scratch1, MemOperand(src, 4, PostIndex)); 483665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Store the "shift" most significant bits of scratch in the least 483765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // signficant bits (i.e., shift down by (32-shift)). 483865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ rsb(scratch2, left_shift, Operand(32)); 483965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register right_shift = scratch2; 484065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch1, Operand(scratch1, LSR, right_shift)); 484165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 484265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&loop); 484365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(scratch3, MemOperand(src, 4, PostIndex)); 484465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch5, limit, Operand(dest)); 484565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift)); 484665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(scratch1, MemOperand(dest, 4, PostIndex)); 484765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch1, Operand(scratch3, LSR, right_shift)); 484865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Loop if four or more bytes left to copy. 484965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Compare to eight, because we did the subtract before increasing dst. 485065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch5, scratch5, Operand(8), SetCC); 485165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ge, &loop); 485265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 485365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // There is now between zero and three bytes left to copy (negative that 485465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // number is in scratch5), and between one and three bytes already read into 485565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // scratch1 (eight times that number in scratch4). We may have read past 485665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // the end of the string, but because objects are aligned, we have not read 485765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // past the end of the object. 485865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Find the minimum of remaining characters to move and preloaded characters 485965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // and write those as bytes. 486065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(scratch5, scratch5, Operand(4), SetCC); 486165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &done); 486265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch4, Operand(scratch5, LSL, 3), ne); 486365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Move minimum of bytes read and bytes left to copy to scratch4. 486465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch5, Operand(scratch4, LSR, 3), LeaveCC, lt); 486565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Between one and three (value in scratch5) characters already read into 486665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // scratch ready to write. 486765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch5, Operand(2)); 486865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 486965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge); 487065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge); 487165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, gt); 487265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch1, MemOperand(dest, 1, PostIndex), gt); 487365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Copy any remaining bytes. 487465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(&byte_loop); 487565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 487665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Simple loop. 487765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Copy words from src to dst, until less than four bytes left. 487865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Both src and dest are word aligned. 487965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&simple_loop); 488065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org { 488165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label loop; 488265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&loop); 488365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(scratch1, MemOperand(src, 4, PostIndex)); 488465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch3, limit, Operand(dest)); 488565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(scratch1, MemOperand(dest, 4, PostIndex)); 488665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Compare to 8, not 4, because we do the substraction before increasing 488765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // dest. 488865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch3, Operand(8)); 488965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ge, &loop); 489065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 489165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 489265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Copy bytes from src to dst until dst hits limit. 489365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&byte_loop); 489465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(dest, Operand(limit)); 489565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); 489665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ge, &done); 489765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 489865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(&byte_loop); 489965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 490065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&done); 490165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 490265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 490365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 49044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, 490565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register c1, 490665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register c2, 490765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch1, 490865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch2, 490965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch3, 491065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch4, 491165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch5, 491265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label* not_found) { 491365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Register scratch3 is the general scratch register in this function. 491465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch = scratch3; 491565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 491665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Make sure that both characters are not digits as such strings has a 49174a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // different hash algorithm. Don't try to look for these in the string table. 491865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label not_array_index; 491965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch, c1, Operand(static_cast<int>('0'))); 492065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); 492165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(hi, ¬_array_index); 492265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch, c2, Operand(static_cast<int>('0'))); 492365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch, Operand(static_cast<int>('9' - '0'))); 492465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 492565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If check failed combine both characters into single halfword. 492665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // This is required by the contract of the method: code at the 492765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // not_found branch expects this combination in c1 register 492865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls); 492965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ls, not_found); 493065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 493165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(¬_array_index); 493265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Calculate the two character string hash. 493365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register hash = scratch1; 493465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StringHelper::GenerateHashInit(masm, hash, c1); 493565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StringHelper::GenerateHashAddCharacter(masm, hash, c2); 493665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StringHelper::GenerateHashGetHash(masm, hash); 493765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 493865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Collect the two characters in a register. 493965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register chars = c1; 494065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte)); 494165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 494265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 494365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash: hash of two character string. 494465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 49454a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Load string table 49464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Load address of first element of the string table. 49474a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register string_table = c2; 49484a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ LoadRoot(string_table, Heap::kStringTableRootIndex); 494965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 495065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register undefined = scratch4; 495165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 495265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 49534a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Calculate capacity mask from the string table capacity. 495465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register mask = scratch2; 49554a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldr(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset)); 495665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(mask, Operand(mask, ASR, 1)); 495765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(mask, mask, Operand(1)); 495865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 49594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Calculate untagged address of the first element of the string table. 49604a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register first_string_table_element = string_table; 49614a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ add(first_string_table_element, string_table, 49624a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Operand(StringTable::kElementsStartOffset - kHeapObjectTag)); 496365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 496465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Registers 496565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // chars: two character string, char 1 in byte 0 and char 2 in byte 1. 496665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash: hash of two character string 496765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // mask: capacity mask 49684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // first_string_table_element: address of the first element of 49694a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // the string table 4970badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // undefined: the undefined object 497165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // scratch: - 497265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 49734a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Perform a number of probes in the string table. 49741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kProbes = 4; 49754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Label found_in_string_table; 497665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label next_probe[kProbes]; 49772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org Register candidate = scratch5; // Scratch register contains candidate. 497865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org for (int i = 0; i < kProbes; i++) { 49794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Calculate entry in string table. 498065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org if (i > 0) { 49814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ add(candidate, hash, Operand(StringTable::GetProbeOffset(i))); 498265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } else { 498365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(candidate, hash); 498465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 498565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 498665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ and_(candidate, candidate, Operand(mask)); 498765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 498865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Load the entry from the symble table. 49894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org STATIC_ASSERT(StringTable::kEntrySize == 1); 499065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(candidate, 49914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org MemOperand(first_string_table_element, 499265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org candidate, 499365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org LSL, 499465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org kPointerSizeLog2)); 499565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 499665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If entry is undefined no string with this hash can be found. 4997badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org Label is_string; 4998badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE); 4999badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ b(ne, &is_string); 5000badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org 5001badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ cmp(undefined, candidate); 500265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, not_found); 50032c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org // Must be the hole (deleted entry). 5004badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org if (FLAG_debug_code) { 50052c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 5006badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ cmp(ip, candidate); 5007594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kOddballInStringTableIsNotUndefinedOrTheHole); 5008badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org } 5009badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ jmp(&next_probe[i]); 5010badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org 5011badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ bind(&is_string); 5012badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org 5013badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // Check that the candidate is a non-external ASCII string. The instance 5014badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // type is still in the scratch register from the CompareObjectType 5015badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // operation. 5016badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); 501765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 501865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If length is not 2 the string is not a candidate. 501965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); 502065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(scratch, Operand(Smi::FromInt(2))); 502165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &next_probe[i]); 502265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 502365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check if the two characters match. 502465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Assumes that word load is little endian. 5025fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize)); 502665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(chars, scratch); 50274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ b(eq, &found_in_string_table); 502865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&next_probe[i]); 502965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 503065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 503165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // No matching 2 character string found by probing. 503265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(not_found); 503365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 503465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Scratch register contains result when we fall through to here. 50352c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org Register result = candidate; 50364a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&found_in_string_table); 503765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Move(r0, result); 503865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 503965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 504065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 504165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashInit(MacroAssembler* masm, 504265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register hash, 504365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register character) { 504465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash = character + (character << 10); 5045f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com __ LoadRoot(hash, Heap::kHashSeedRootIndex); 5046fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // Untag smi seed and add the character. 5047fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org __ add(hash, character, Operand(hash, LSR, kSmiTagSize)); 5048fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // hash += hash << 10; 5049fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org __ add(hash, hash, Operand(hash, LSL, 10)); 505065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash ^= hash >> 6; 50512c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org __ eor(hash, hash, Operand(hash, LSR, 6)); 505265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 505365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 505465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 505565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, 505665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register hash, 505765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register character) { 505865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash += character; 505965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(hash, hash, Operand(character)); 506065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash += hash << 10; 506165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(hash, hash, Operand(hash, LSL, 10)); 506265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash ^= hash >> 6; 50632c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org __ eor(hash, hash, Operand(hash, LSR, 6)); 506465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 506565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 506665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 506765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringHelper::GenerateHashGetHash(MacroAssembler* masm, 506865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register hash) { 506965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash += hash << 3; 507065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(hash, hash, Operand(hash, LSL, 3)); 507165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash ^= hash >> 11; 50722c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org __ eor(hash, hash, Operand(hash, LSR, 11)); 507365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // hash += hash << 15; 5074f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com __ add(hash, hash, Operand(hash, LSL, 15)); 507565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 5076f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com __ and_(hash, hash, Operand(String::kHashBitMask), SetCC); 50772c4567981e65b51f161283f8635e110a73629c9ddanno@chromium.org 507865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // if (hash == 0) hash = 27; 5079f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com __ mov(hash, Operand(StringHasher::kZeroHash), LeaveCC, eq); 508065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 508165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 508265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 508365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid SubStringStub::Generate(MacroAssembler* masm) { 508465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label runtime; 508565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 508665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Stack frame on entry. 508765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // lr: return address 508865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[0]: to 508965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[4]: from 509065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[8]: string 509165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 509265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // This stub is called from the native-call %_SubString(...), so 509365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // nothing can be assumed about the arguments. It is tested that: 509465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // "string" is a sequential string, 509565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // both "from" and "to" are smis, and 509665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // 0 <= from <= to <= string.length. 509765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If any of these assumptions fail, we call the runtime system. 509865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 50991456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kToOffset = 0 * kPointerSize; 51001456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kFromOffset = 1 * kPointerSize; 51011456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org const int kStringOffset = 2 * kPointerSize; 510265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 51037ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); 5104d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com STATIC_ASSERT(kFromOffset == kToOffset + 4); 510565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 510665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 51074668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org 5108e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // Arithmetic shift right by one un-smi-tags. In this case we rotate right 5109e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // instead because we bail out on non-smi values: ROR and ASR are equivalent 5110e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // for smis but they set the flags in a way that's easier to optimize. 5111e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ mov(r2, Operand(r2, ROR, 1), SetCC); 5112e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ mov(r3, Operand(r3, ROR, 1), SetCC, cc); 5113e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // If either to or from had the smi tag bit set, then C is set now, and N 5114e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // has the same value: we rotated by 1, so the bottom bit is now the top bit. 5115fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // We want to bailout to runtime here if From is negative. In that case, the 5116fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // next instruction is not executed and we fall through to bailing out to 5117e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // runtime. 5118e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // Executed if both r2 and r3 are untagged integers. 5119e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ sub(r2, r2, Operand(r3), SetCC, cc); 5120e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // One of the above un-smis or the above SUB could have set N==1. 5121e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ b(mi, &runtime); // Either "from" or "to" is not an smi, or from > to. 512265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 51237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Make sure first argument is a string. 51241805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ ldr(r0, MemOperand(sp, kStringOffset)); 5125e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // Do a JumpIfSmi, but fold its jump into the subsequent string test. 5126bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiTst(r0); 5127e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org Condition is_string = masm->IsObjectStringType(r0, r1, ne); 5128e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org ASSERT(is_string == eq); 512965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(NegateCondition(is_string), &runtime); 513065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 51312e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org Label single_char; 51322e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ cmp(r2, Operand(1)); 51332e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ b(eq, &single_char); 51342e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org 51351805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // Short-cut for the case of trivial substring. 51361805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org Label return_r0; 51371805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r0: original string 51381805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r2: result string length 51391805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset)); 51401805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ cmp(r2, Operand(r4, ASR, 1)); 5141ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com // Return original string. 51421805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ b(eq, &return_r0); 5143ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com // Longer than original string's length or negative: unsafe arguments. 5144ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com __ b(hi, &runtime); 5145ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com // Shorter than original string's length: an actual substring. 51461805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 51477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Deal with different string types: update the index if necessary 51487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // and put the underlying string into r5. 51497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r0: original string 51507ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r1: instance type 51517ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r2: length 51527ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r3: from index (untagged) 51537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label underlying_unpacked, sliced_string, seq_or_external_string; 51547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // If the string is not indirect, it can only be sequential or external. 51557ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 51567ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kIsIndirectStringMask != 0); 51577ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r1, Operand(kIsIndirectStringMask)); 51587ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(eq, &seq_or_external_string); 51597ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 51607ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r1, Operand(kSlicedNotConsMask)); 51617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &sliced_string); 51627ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Cons string. Check whether it is flat, then fetch first part. 51637ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset)); 51644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ CompareRoot(r5, Heap::kempty_stringRootIndex); 51657ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &runtime); 51667ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); 51677ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Update instance type. 51687ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); 51697ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 51707ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ jmp(&underlying_unpacked); 51717ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 51727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&sliced_string); 51737ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Sliced string. Fetch parent and correct start index by offset. 51747ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); 5175bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset)); 5176fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ add(r3, r3, Operand(r4, ASR, 1)); // Add offset to index. 51777ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Update instance type. 51787ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); 51797ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 51807ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ jmp(&underlying_unpacked); 51817ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 51827ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&seq_or_external_string); 51837ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Sequential or external string. Just move string to the expected register. 51847ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ mov(r5, r0); 51857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 51867ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&underlying_unpacked); 518765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 51887ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org if (FLAG_string_slices) { 51897ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label copy_routine; 51907ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r5: underlying subject string 51917ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r1: instance type of underlying subject string 51927ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r2: length 51937ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r3: adjusted start index (untagged) 51947ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ cmp(r2, Operand(SlicedString::kMinLength)); 51957ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Short slice. Copy instead of slicing. 51967ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(lt, ©_routine); 51977ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Allocate new sliced string. At this point we do not reload the instance 51987ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // type including the string encoding because we simply rely on the info 51997ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // provided by the original string. It does not matter if the original 52007ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // string's encoding is wrong because we always have to recheck encoding of 52017ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // the newly created string's parent anyways due to externalized strings. 52027ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label two_byte_slice, set_slice_header; 5203e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 52047ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 52057ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r1, Operand(kStringEncodingMask)); 52067ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(eq, &two_byte_slice); 52077ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateAsciiSlicedString(r0, r2, r6, r7, &runtime); 52087ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ jmp(&set_slice_header); 52097ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&two_byte_slice); 52107ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime); 52117ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&set_slice_header); 52127ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ mov(r3, Operand(r3, LSL, 1)); 52137ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); 5214bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset)); 52157ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ jmp(&return_r0); 52161805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 52177ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(©_routine); 52187ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org } 521965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 52207ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r5: underlying subject string 52217ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r1: instance type of underlying subject string 52227ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r2: length 52237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r3: adjusted start index (untagged) 52247ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label two_byte_sequential, sequential_string, allocate_result; 52257ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kExternalStringTag != 0); 52267ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 52277ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r1, Operand(kExternalStringTag)); 52287ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(eq, &sequential_string); 52297ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 52307ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Handle external string. 52317ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Rule out short external strings. 52327ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_CHECK(kShortExternalStringTag != 0); 52337ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r1, Operand(kShortExternalStringTag)); 52347ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &runtime); 52357ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset)); 52367ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r5 already points to the first character of underlying string. 52377ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ jmp(&allocate_result); 52387ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 52397ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&sequential_string); 52407ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Locate first character of underlying subject string. 5241fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 5242fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 52437ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 52447ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&allocate_result); 52457ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Sequential acii string. Allocate the result. 5246e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 52477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r1, Operand(kStringEncodingMask)); 52487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(eq, &two_byte_sequential); 52497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 52502efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org // Allocate and copy the resulting ASCII string. 52517ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime); 52527ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 52537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Locate first character of substring to copy. 52547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ add(r5, r5, r3); 525565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Locate first character of result. 5256fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 525765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 52581805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r0: result string 52591805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r1: first character of result string 52601805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r2: result string length 52611805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r5: first character of substring to copy 5262fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 526365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 526465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org COPY_ASCII | DEST_ALWAYS_ALIGNED); 52651805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ jmp(&return_r0); 526665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 52677ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Allocate and copy the resulting two-byte string. 52687ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&two_byte_sequential); 52697ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime); 527065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 52717ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Locate first character of substring to copy. 52721805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 52737ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ add(r5, r5, Operand(r3, LSL, 1)); 527465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Locate first character of result. 527565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 52761805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 527765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: result string. 527865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: first character of result. 527965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: result length. 52801805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org // r5: first character of substring to copy. 528165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 5282d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com StringHelper::GenerateCopyCharactersLong( 5283d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED); 52841805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org 52851805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org __ bind(&return_r0); 52867ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Counters* counters = masm->isolate()->counters(); 52877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); 52882e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ Drop(3); 528965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 529065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 529165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Just jump to runtime to create the sub string. 529265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&runtime); 529365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ TailCallRuntime(Runtime::kSubString, 3, 1); 52942e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org 52952e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ bind(&single_char); 52962e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org // r0: original string 52972e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org // r1: instance type 52982e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org // r2: length 52992e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org // r3: from index (untagged) 53002e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ SmiTag(r3, r3); 53012e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org StringCharAtGenerator generator( 53022e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org r0, r3, r2, r0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); 53032e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org generator.GenerateFast(masm); 53042e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ Drop(3); 53052e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org __ Ret(); 53062e04b58f1dc7cee8fdf047b5dbc9dc93e767821dulan@chromium.org generator.SkipSlow(masm, &runtime); 530765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 530865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 530965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 53101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, 53111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register left, 53121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register right, 53131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register scratch1, 53141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register scratch2, 53151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register scratch3) { 53161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register length = scratch1; 53171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 53181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compare lengths. 53191c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label strings_not_equal, check_zero_length; 53201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(length, FieldMemOperand(left, String::kLengthOffset)); 53211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); 53221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ cmp(length, scratch2); 53231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(eq, &check_zero_length); 53241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&strings_not_equal); 53251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(r0, Operand(Smi::FromInt(NOT_EQUAL))); 53261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(); 53271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 53281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Check if the length is zero. 53291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label compare_chars; 53301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&check_zero_length); 53311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org STATIC_ASSERT(kSmiTag == 0); 533259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(length, Operand::Zero()); 53331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(ne, &compare_chars); 53341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(r0, Operand(Smi::FromInt(EQUAL))); 53351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(); 53361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 53371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compare characters. 53381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&compare_chars); 53391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org GenerateAsciiCharsCompareLoop(masm, 53401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org left, right, length, scratch2, scratch3, 53411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org &strings_not_equal); 53421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 53431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Characters are equal. 53441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(r0, Operand(Smi::FromInt(EQUAL))); 53451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(); 53461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org} 53471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 53481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 534965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 535065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register left, 535165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register right, 535265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch1, 535365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch2, 535465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch3, 535565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register scratch4) { 53561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label result_not_equal, compare_lengths; 535765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Find minimum length and length difference. 535865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); 535965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); 536065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ sub(scratch3, scratch1, Operand(scratch2), SetCC); 536165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register length_delta = scratch3; 536265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(scratch1, scratch2, LeaveCC, gt); 536365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Register min_length = scratch1; 536465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 536559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(min_length, Operand::Zero()); 536665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &compare_lengths); 536765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 53681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compare loop. 53691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org GenerateAsciiCharsCompareLoop(masm, 53701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org left, right, min_length, scratch2, scratch4, 53711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org &result_not_equal); 537265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 53731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compare lengths - strings up to min-length are equal. 537465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&compare_lengths); 537565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 53761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Use length_delta as result if it's zero. 53771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(r0, Operand(length_delta), SetCC); 53781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&result_not_equal); 53791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Conditionally update the result based either on length_delta or 53801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // the last comparion performed in the loop above. 538165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt); 538265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt); 538365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 538465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 538565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 538665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 53871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid StringCompareStub::GenerateAsciiCharsCompareLoop( 53881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org MacroAssembler* masm, 53891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register left, 53901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register right, 53911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register length, 53921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register scratch1, 53931c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register scratch2, 53941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label* chars_not_equal) { 53951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Change index to run from -length to -1 by adding length to string 53961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // start. This means that loop ends when index reaches zero, which 53971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // doesn't need an additional compare. 53981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ SmiUntag(length); 53991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(scratch1, length, 5400fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 54011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(left, left, Operand(scratch1)); 54021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(right, right, Operand(scratch1)); 5403ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ rsb(length, length, Operand::Zero()); 54041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register index = length; // index = -length; 54051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 54061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compare loop. 54071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label loop; 54081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&loop); 54091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldrb(scratch1, MemOperand(left, index)); 54101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldrb(scratch2, MemOperand(right, index)); 54111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ cmp(scratch1, scratch2); 54121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(ne, chars_not_equal); 54131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(index, index, Operand(1), SetCC); 54141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(ne, &loop); 54151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org} 54161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 54171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 541865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringCompareStub::Generate(MacroAssembler* masm) { 541965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label runtime; 542065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 54217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Counters* counters = masm->isolate()->counters(); 54227979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org 542365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Stack frame on entry. 542465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[0]: right string 542565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // sp[4]: left string 5426d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1. 542765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 542865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label not_same; 542965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r0, r1); 543065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, ¬_same); 543165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(EQUAL == 0); 543265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 543365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(Smi::FromInt(EQUAL))); 54347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_compare_native(), 1, r1, r2); 543565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 543665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 543765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 543865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(¬_same); 543965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 5440badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // Check that both objects are sequential ASCII strings. 5441d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); 544265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 5443badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // Compare flat ASCII strings natively. Remove arguments from stack first. 54447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_compare_native(), 1, r2, r3); 544565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 5446d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); 544765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 544865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 544965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // tagged as a small integer. 545065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&runtime); 545165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 545265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 545365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 545465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 545565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid StringAddStub::Generate(MacroAssembler* masm) { 54567ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label call_runtime, call_builtin; 54573a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Builtins::JavaScript builtin_id = Builtins::ADD; 54583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 54597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Counters* counters = masm->isolate()->counters(); 54607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org 546165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Stack on entry: 54623a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // sp[0]: second argument (right). 54633a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // sp[4]: first argument (left). 546465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 546565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Load the two arguments. 546665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. 546765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. 546865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 546965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Make sure that both arguments are strings if not known in advance. 5470ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // Otherwise, at least one of the arguments is definitely a string, 5471ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org // and we convert the one that is not known to be a string. 5472ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if ((flags_ & STRING_ADD_CHECK_BOTH) == STRING_ADD_CHECK_BOTH) { 5473ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT); 5474ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT); 54757ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ JumpIfEitherSmi(r0, r1, &call_runtime); 547665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Load instance types. 547765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 547865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 547965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 548065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 548165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kStringTag == 0); 548265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If either is not a string, go to runtime. 548365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r4, Operand(kIsNotStringMask)); 548465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r5, Operand(kIsNotStringMask), eq); 54857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &call_runtime); 5486ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } else if ((flags_ & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { 5487ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ASSERT((flags_ & STRING_ADD_CHECK_RIGHT) == 0); 5488ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GenerateConvertArgument( 5489ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org masm, 1 * kPointerSize, r0, r2, r3, r4, r5, &call_builtin); 5490ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org builtin_id = Builtins::STRING_ADD_RIGHT; 5491ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org } else if ((flags_ & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { 5492ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org ASSERT((flags_ & STRING_ADD_CHECK_LEFT) == 0); 5493ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org GenerateConvertArgument( 5494ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org masm, 0 * kPointerSize, r1, r2, r3, r4, r5, &call_builtin); 5495ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org builtin_id = Builtins::STRING_ADD_LEFT; 549665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 549765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 549865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Both arguments are strings. 549965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: first string 550065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: second string 55013a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 55023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 550365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org { 550465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label strings_not_empty; 550565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check if either of the strings are empty. In that case return the other. 550665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); 550765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); 550865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 550965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. 551065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. 551165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 551265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Else test if second string is empty. 551365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r3, Operand(Smi::FromInt(0)), ne); 551465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &strings_not_empty); // If either string was empty, return r0. 551565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 55167979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 551765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 551865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 551965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 552065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&strings_not_empty); 552165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 552265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 5523bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r2); 5524bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(r3); 552565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Both strings are non-empty. 552665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: first string 552765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: second string 552865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: length of first string 552965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: length of second string 55303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 55313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 553265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Look at the length of the result of adding the two strings. 553365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label string_add_flat_result, longer_than_two; 553465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Adding two lengths can't overflow. 553565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); 553665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(r6, r2, Operand(r3)); 55374a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Use the string table when adding two one character strings, as it 55384a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // helps later optimizations to return a string here. 553965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r6, Operand(2)); 554065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &longer_than_two); 554165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 5542badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // Check that both strings are non-external ASCII strings. 5543ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { 554465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 554565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 554665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 554765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 554865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 554965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, 55507ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org &call_runtime); 555165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 555265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Get the two characters forming the sub string. 5553fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); 5554fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize)); 555565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 55564a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Try to lookup two character string in string table. If it is not found 555765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // just allocate a new one. 555865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label make_two_character_string; 55594a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org StringHelper::GenerateTwoCharacterStringTableProbe( 556065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); 55617979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 556265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 556365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 556465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 556565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&make_two_character_string); 556665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Resulting string has length 2 and first chars of two strings 556765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // are combined into single halfword in r2 register. 556865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // So we can fill resulting string without two loops by a single 556965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // halfword store instruction (which assumes that processor is 557065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // in a little endian mode) 557165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r6, Operand(2)); 55727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); 5573fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ strh(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); 55747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 557565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 557665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 557765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 557865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&longer_than_two); 557965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Check if resulting string will be flat. 55802efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org __ cmp(r6, Operand(ConsString::kMinLength)); 558165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(lt, &string_add_flat_result); 558265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Handle exceptionally long strings in the runtime system. 558365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); 558465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org ASSERT(IsPowerOf2(String::kMaxLength + 1)); 558565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. 558665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ cmp(r6, Operand(String::kMaxLength + 1)); 55877ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(hs, &call_runtime); 558865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 558965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // If result is not supposed to be flat, allocate a cons string object. 5590badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org // If both strings are ASCII the result is an ASCII cons string. 5591ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { 559265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 559365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 559465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 559565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 559665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 559765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org Label non_ascii, allocated, ascii_data; 559865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kTwoByteStringTag == 0); 559965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r4, Operand(kStringEncodingMask)); 560065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r5, Operand(kStringEncodingMask), ne); 560165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &non_ascii); 560265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 560365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Allocate an ASCII cons string. 560465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&ascii_data); 56057ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime); 560665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&allocated); 560765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Fill the fields of the cons string. 560857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org Label skip_write_barrier, after_writing; 560957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org ExternalReference high_promotion_mode = ExternalReference:: 561057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org new_space_high_promotion_mode_active_address(masm->isolate()); 561157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ mov(r4, Operand(high_promotion_mode)); 561257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ ldr(r4, MemOperand(r4, 0)); 561357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ cmp(r4, Operand::Zero()); 561457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ b(eq, &skip_write_barrier); 561557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 561665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); 561757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ RecordWriteField(r7, 561857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org ConsString::kFirstOffset, 561957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org r0, 562057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org r4, 562157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org kLRHasNotBeenSaved, 562257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org kDontSaveFPRegs); 562365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); 562457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ RecordWriteField(r7, 562557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org ConsString::kSecondOffset, 562657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org r1, 562757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org r4, 562857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org kLRHasNotBeenSaved, 562957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org kDontSaveFPRegs); 563057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ jmp(&after_writing); 563157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 563257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ bind(&skip_write_barrier); 563357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); 563457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); 563557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 563657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org __ bind(&after_writing); 563757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org 563865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ mov(r0, Operand(r7)); 56397979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 564065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 564165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 564265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 564365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&non_ascii); 564465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // At least one of the strings is two-byte. Check whether it happens 5645ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // to contain only one byte characters. 564665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r4: first instance type. 564765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r5: second instance type. 5648ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ tst(r4, Operand(kOneByteDataHintMask)); 5649ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ tst(r5, Operand(kOneByteDataHintMask), ne); 565065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(ne, &ascii_data); 565146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org __ eor(r4, r4, Operand(r5)); 5652ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org STATIC_ASSERT(kOneByteStringTag != 0 && kOneByteDataHintTag != 0); 5653ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ and_(r4, r4, Operand(kOneByteStringTag | kOneByteDataHintTag)); 5654ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ cmp(r4, Operand(kOneByteStringTag | kOneByteDataHintTag)); 565546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org __ b(eq, &ascii_data); 565665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 565765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Allocate a two byte cons string. 56587ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime); 565965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ jmp(&allocated); 566065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 56617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // We cannot encounter sliced strings or cons strings here since: 56622efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength); 56637ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Handle creating a flat result from either external or sequential strings. 56647ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Locate the first characters' locations. 566565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r0: first string 566665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r1: second string 566765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: length of first string 566865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: length of second string 56693a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) 56703a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) 567165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r6: sum of lengths. 56727ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label first_prepared, second_prepared; 567365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&string_add_flat_result); 5674ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if ((flags_ & STRING_ADD_CHECK_BOTH) != STRING_ADD_CHECK_BOTH) { 567565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); 567665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); 567765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 567865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); 567965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org } 56807ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 56817ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Check whether both strings have same encoding 56827ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ eor(r7, r4, Operand(r5)); 56837ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r7, Operand(kStringEncodingMask)); 56847ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &call_runtime); 56857ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 568665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 568765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ tst(r4, Operand(kStringRepresentationMask)); 5688fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); 56897ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ add(r7, 56907ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org r0, 5691fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag), 56927ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org LeaveCC, 56937ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org eq); 56947ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(eq, &first_prepared); 56957ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // External string: rule out short external string and load string resource. 56967ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kShortExternalStringTag != 0); 56977ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r4, Operand(kShortExternalStringMask)); 56987ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &call_runtime); 56997ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset)); 57007ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&first_prepared); 57017ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 57027ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kSeqStringTag == 0); 57037ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r5, Operand(kStringRepresentationMask)); 5704fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); 57057ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ add(r1, 57067ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org r1, 5707fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag), 57087ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org LeaveCC, 57097ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org eq); 57107ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(eq, &second_prepared); 57117ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // External string: rule out short external string and load string resource. 57127ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kShortExternalStringTag != 0); 57137ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r5, Operand(kShortExternalStringMask)); 57147ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ b(ne, &call_runtime); 57157ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset)); 57167ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&second_prepared); 57177ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org 57187ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org Label non_ascii_string_add_flat_result; 57197ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r7: first character of first string 57207ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r1: first character of second string 572165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: length of first string. 572265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: length of second string. 57237ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r6: sum of lengths. 57247ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // Both strings have the same encoding. 57257ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org STATIC_ASSERT(kTwoByteStringTag == 0); 57267ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ tst(r5, Operand(kStringEncodingMask)); 572765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ b(eq, &non_ascii_string_add_flat_result); 572865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 57297ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); 5730fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ add(r6, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 57317ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r0: result string. 57327ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r7: first character of first string. 57337ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r1: first character of second string. 573465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: length of first string. 573565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: length of second string. 573665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r6: first character of result. 57377ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true); 573865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r6: next character of result. 573965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); 57407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 574165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 574265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 574365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 574465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ bind(&non_ascii_string_add_flat_result); 57457ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime); 57467ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 57477ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r0: result string. 57487ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r7: first character of first string. 57497ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r1: first character of second string. 575065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r2: length of first string. 575165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r3: length of second string. 575265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // r6: first character of result. 57537ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false); 57547ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org // r6: next character of result. 575565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); 57567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_add_native(), 1, r2, r3); 575765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ add(sp, sp, Operand(2 * kPointerSize)); 575865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org __ Ret(); 575965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 576065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org // Just jump to runtime to add the two strings. 57617ad65226b3ba6f9250a5ee869ee77e2b9258fc91ricow@chromium.org __ bind(&call_runtime); 5762ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { 57634e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPop(masm); 57644e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org // Build a frame 57654e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org { 57664e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 57674e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPush(masm); 57684e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ CallRuntime(Runtime::kStringAdd, 2); 57694e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 57704e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ Ret(); 57714e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } else { 57724e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 57734e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 57743a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 57753a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org if (call_builtin.is_linked()) { 57763a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(&call_builtin); 5777ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org if ((flags_ & STRING_ADD_ERECT_FRAME) != 0) { 57784e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPop(masm); 57794e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org // Build a frame 57804e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org { 57814e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 57824e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org GenerateRegisterArgsPush(masm); 57834e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ InvokeBuiltin(builtin_id, CALL_FUNCTION); 57844e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 57854e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ Ret(); 57864e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } else { 57874e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); 57884e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org } 57893a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org } 57903a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org} 57913a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 57923a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 57934e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgvoid StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 57944e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ push(r0); 57954e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ push(r1); 57964e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org} 57974e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org 57984e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org 57994e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgvoid StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm) { 58004e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ pop(r1); 58014e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org __ pop(r0); 58024e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org} 58034e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org 58044e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org 58053a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.orgvoid StringAddStub::GenerateConvertArgument(MacroAssembler* masm, 58063a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org int stack_offset, 58073a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Register arg, 58083a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Register scratch1, 58093a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Register scratch2, 58103a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Register scratch3, 58113a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Register scratch4, 58123a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Label* slow) { 58133a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // First check if the argument is already a string. 58143a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Label not_string, done; 58153a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ JumpIfSmi(arg, ¬_string); 58163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ CompareObjectType(arg, scratch1, scratch1, FIRST_NONSTRING_TYPE); 58173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ b(lt, &done); 58183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 58193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Check the number to string cache. 58203a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Label not_cached; 58213a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(¬_string); 58223a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Puts the cached result into scratch1. 58233a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org NumberToStringStub::GenerateLookupNumberStringCache(masm, 58243a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org arg, 58253a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org scratch1, 58263a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org scratch2, 58273a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org scratch3, 58283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org scratch4, 58293a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org ¬_cached); 58303a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ mov(arg, scratch1); 58313a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ str(arg, MemOperand(sp, stack_offset)); 58323a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ jmp(&done); 58333a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 58343a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org // Check if the argument is a safe string wrapper. 58353a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(¬_cached); 58363a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ JumpIfSmi(arg, slow); 58373a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ CompareObjectType( 58383a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org arg, scratch1, scratch2, JS_VALUE_TYPE); // map -> scratch1. 58393a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ b(ne, slow); 58403a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset)); 58413a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ and_(scratch2, 58423a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org scratch2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 58433a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ cmp(scratch2, 58443a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 58453a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ b(ne, slow); 58463a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ ldr(arg, FieldMemOperand(arg, JSValue::kValueOffset)); 58473a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ str(arg, MemOperand(sp, stack_offset)); 58483a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org 58493a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org __ bind(&done); 585065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} 585165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 585265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 5853a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid ICCompareStub::GenerateSmis(MacroAssembler* masm) { 5854fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(state_ == CompareIC::SMI); 5855a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label miss; 5856a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ orr(r2, r1, r0); 58577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfNotSmi(r2, &miss); 5858a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5859a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (GetCondition() == eq) { 5860a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // For equality we do not care about the sign of the result. 5861a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ sub(r0, r0, r1, SetCC); 5862a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } else { 5863496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org // Untag before subtracting to avoid handling overflow. 5864496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org __ SmiUntag(r1); 5865bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ sub(r0, r1, Operand::SmiUntag(r0)); 5866a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 5867a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ Ret(); 5868a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5869a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&miss); 5870a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org GenerateMiss(masm); 5871a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 5872a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5873a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 58748432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid ICCompareStub::GenerateNumbers(MacroAssembler* masm) { 58758432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org ASSERT(state_ == CompareIC::NUMBER); 5876a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5877a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label generic_stub; 58789a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org Label unordered, maybe_undefined1, maybe_undefined2; 5879a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label miss; 5880a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5881fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (left_ == CompareIC::SMI) { 5882fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(r1, &miss); 5883fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 5884fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org if (right_ == CompareIC::SMI) { 5885fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfNotSmi(r0, &miss); 5886fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org } 5887a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5888a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Inlining the double comparison and falling back to the general compare 5889e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // stub if NaN is involved. 5890e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Load left and right operand. 5891e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org Label done, left, left_smi, right_smi; 5892e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ JumpIfSmi(r0, &right_smi); 5893e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, 5894e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org DONT_DO_SMI_CHECK); 5895e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r2, r0, Operand(kHeapObjectTag)); 5896e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d1, r2, HeapNumber::kValueOffset); 5897e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(&left); 5898e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&right_smi); 5899bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d1, r0); 5900e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org 5901e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&left); 5902e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ JumpIfSmi(r1, &left_smi); 5903e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ CheckMap(r1, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, 5904e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org DONT_DO_SMI_CHECK); 5905e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ sub(r2, r1, Operand(kHeapObjectTag)); 5906e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ vldr(d0, r2, HeapNumber::kValueOffset); 5907e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(&done); 5908e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&left_smi); 5909bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiToDouble(d0, r1); 5910a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5911e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ bind(&done); 5912e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Compare operands. 5913e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ VFPCompareAndSetFlags(d0, d1); 5914a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5915e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Don't base result on status bits when a NaN is involved. 5916e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ b(vs, &unordered); 5917a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5918e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org // Return a result of -1, 0, or 1, based on status bits. 5919e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(EQUAL), LeaveCC, eq); 5920e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(LESS), LeaveCC, lt); 5921e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ mov(r0, Operand(GREATER), LeaveCC, gt); 5922e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ Ret(); 5923a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 59249a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ bind(&unordered); 5925a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&generic_stub); 5926fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ICCompareStub stub(op_, CompareIC::GENERIC, CompareIC::GENERIC, 5927fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org CompareIC::GENERIC); 59288432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org __ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); 5929a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 59309a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ bind(&maybe_undefined1); 59319a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org if (Token::IsOrderedRelationalCompareOp(op_)) { 59329a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 59339a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ b(ne, &miss); 5934fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ JumpIfSmi(r1, &unordered); 59359a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); 59369a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ b(ne, &maybe_undefined2); 59379a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ jmp(&unordered); 59389a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org } 59399a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org 59409a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ bind(&maybe_undefined2); 59419a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org if (Token::IsOrderedRelationalCompareOp(op_)) { 59429a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); 59439a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org __ b(eq, &unordered); 59449a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org } 59459a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org 5946a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&miss); 5947a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org GenerateMiss(masm); 5948a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 5949a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 5950a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 59514a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { 59524a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org ASSERT(state_ == CompareIC::INTERNALIZED_STRING); 595383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Label miss; 595483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 595583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Registers containing left and right operands respectively. 595683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Register left = r1; 595783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Register right = r0; 595883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Register tmp1 = r2; 595983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Register tmp2 = r3; 596083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 596183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Check that both operands are heap objects. 596283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ JumpIfEitherSmi(left, right, &miss); 596383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 59644a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Check that both operands are internalized strings. 596583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 596683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 596783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 596883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 5969ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 5970ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ orr(tmp1, tmp1, Operand(tmp2)); 5971ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ tst(tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 59721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ b(ne, &miss); 597383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 59744a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Internalized strings are compared by identity. 59754a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ cmp(left, right); 59764a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Make sure r0 is non-zero. At this point input operands are 59774a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // guaranteed to be non-zero. 59784a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org ASSERT(right.is(r0)); 59794a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org STATIC_ASSERT(EQUAL == 0); 59804a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org STATIC_ASSERT(kSmiTag == 0); 59814a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 59824a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ Ret(); 59834a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 59844a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ bind(&miss); 59854a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org GenerateMiss(masm); 59864a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org} 59874a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 59884a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 59894a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.orgvoid ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { 59904a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org ASSERT(state_ == CompareIC::UNIQUE_NAME); 59914a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org ASSERT(GetCondition() == eq); 59924a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Label miss; 59934a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 59944a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Registers containing left and right operands respectively. 59954a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register left = r1; 59964a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register right = r0; 59974a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register tmp1 = r2; 59984a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org Register tmp2 = r3; 59994a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 60004a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Check that both operands are heap objects. 60014a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ JumpIfEitherSmi(left, right, &miss); 60024a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 60034a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Check that both operands are unique names. This leaves the instance 60044a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // types loaded in tmp1 and tmp2. 60054a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 60064a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 60074a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 60084a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 60094a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 60101510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ JumpIfNotUniqueName(tmp1, &miss); 60111510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ JumpIfNotUniqueName(tmp2, &miss); 60124a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org 60134a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Unique names are compared by identity. 601483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ cmp(left, right); 601583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // Make sure r0 is non-zero. At this point input operands are 601683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org // guaranteed to be non-zero. 601783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org ASSERT(right.is(r0)); 601883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org STATIC_ASSERT(EQUAL == 0); 601983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org STATIC_ASSERT(kSmiTag == 0); 602083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 602183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ Ret(); 602283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 602383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ bind(&miss); 602483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org GenerateMiss(masm); 602583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org} 602683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 602783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org 60281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgvoid ICCompareStub::GenerateStrings(MacroAssembler* masm) { 6029fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(state_ == CompareIC::STRING); 60301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label miss; 60311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60324efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org bool equality = Token::IsEqualityOp(op_); 60334efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org 60341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Registers containing left and right operands respectively. 60351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register left = r1; 60361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register right = r0; 60371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register tmp1 = r2; 60381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register tmp2 = r3; 60391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register tmp3 = r4; 60401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register tmp4 = r5; 60411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Check that both operands are heap objects. 60431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ JumpIfEitherSmi(left, right, &miss); 60441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Check that both operands are strings. This leaves the instance 60461c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // types loaded in tmp1 and tmp2. 60471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 60481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 60491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 60501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 60511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org STATIC_ASSERT(kNotStringTag != 0); 60521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ orr(tmp3, tmp1, tmp2); 60531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ tst(tmp3, Operand(kIsNotStringMask)); 60541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(ne, &miss); 60551c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60561c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Fast check for identical strings. 60571c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ cmp(left, right); 60581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org STATIC_ASSERT(EQUAL == 0); 60591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org STATIC_ASSERT(kSmiTag == 0); 60601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 60611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(eq); 60621c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60631c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Handle not identical strings. 60641c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60654a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org // Check that both strings are internalized strings. If they are, we're done 60661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // because we already know they are not identical. We know they are both 60671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // strings. 60684efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org if (equality) { 60694efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org ASSERT(GetCondition() == eq); 6070ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org STATIC_ASSERT(kInternalizedTag == 0); 6071ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ orr(tmp3, tmp1, Operand(tmp2)); 6072ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ tst(tmp3, Operand(kIsNotInternalizedMask)); 60734efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org // Make sure r0 is non-zero. At this point input operands are 60744efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org // guaranteed to be non-zero. 60754efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org ASSERT(right.is(r0)); 6076ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org __ Ret(eq); 60774efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org } 60781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Check that both strings are sequential ASCII. 60801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label runtime; 60814efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org __ JumpIfBothInstanceTypesAreNotSequentialAscii( 60824efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org tmp1, tmp2, tmp3, tmp4, &runtime); 60831c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60841c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compare flat ASCII strings. Returns when done. 60854efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org if (equality) { 60864efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org StringCompareStub::GenerateFlatAsciiStringEquals( 60874efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org masm, left, right, tmp1, tmp2, tmp3); 60884efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org } else { 60894efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org StringCompareStub::GenerateCompareFlatAsciiStrings( 60904efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org masm, left, right, tmp1, tmp2, tmp3, tmp4); 60914efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org } 60921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 60931c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Handle more complex cases in runtime. 60941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&runtime); 60951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Push(left, right); 60964efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org if (equality) { 60974efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 60984efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org } else { 60994efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 61004efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org } 61011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 61021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&miss); 61031c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org GenerateMiss(masm); 61041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org} 61051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 61061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 6107a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid ICCompareStub::GenerateObjects(MacroAssembler* masm) { 6108fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org ASSERT(state_ == CompareIC::OBJECT); 6109a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Label miss; 6110a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ and_(r2, r1, Operand(r0)); 61117b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(r2, &miss); 6112a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 6113a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); 6114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ b(ne, &miss); 6115a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); 6116a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ b(ne, &miss); 6117a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 6118a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org ASSERT(GetCondition() == eq); 6119a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ sub(r0, r0, Operand(r1)); 6120a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ Ret(); 6121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 6122a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&miss); 6123a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org GenerateMiss(masm); 6124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 6125a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 6126a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 612764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { 612864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org Label miss; 612964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ and_(r2, r1, Operand(r0)); 613064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ JumpIfSmi(r2, &miss); 613164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 613264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 613364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ cmp(r2, Operand(known_map_)); 613464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ne, &miss); 613564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ cmp(r3, Operand(known_map_)); 613664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ b(ne, &miss); 613764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 613864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ sub(r0, r0, Operand(r1)); 613964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ Ret(); 614064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 614164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ bind(&miss); 614264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org GenerateMiss(masm); 614364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org} 614464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 614564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 6146a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 614764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid ICCompareStub::GenerateMiss(MacroAssembler* masm) { 6148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 614964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Call the runtime system in a fresh internal frame. 615064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org ExternalReference miss = 615164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate()); 615264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 6153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 6154c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Push(r1, r0); 615564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ push(lr); 615664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ Push(r1, r0); 6157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ip, Operand(Smi::FromInt(op_))); 6158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ip); 6159c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallExternalReference(miss, 3); 616064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Compute the entry point of the rewritten stub. 616164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 616264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org // Restore registers. 616364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ pop(lr); 616464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ pop(r0); 616564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org __ pop(r1); 6166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 616764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org 6168a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ Jump(r2); 6169a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 6170a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 6171a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 617283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.orgvoid DirectCEntryStub::Generate(MacroAssembler* masm) { 617383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org __ ldr(pc, MemOperand(sp, 0)); 617483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org} 617583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 617683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 617783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.orgvoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, 617849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org Register target) { 61798432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org intptr_t code = 61808432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org reinterpret_cast<intptr_t>(GetCode(masm->isolate()).location()); 61818432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org __ mov(lr, Operand(code, RelocInfo::CODE_TARGET)); 61827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 61837028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // Prevent literal pool emission during calculation of return address. 61847028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org Assembler::BlockConstPoolScope block_const_pool(masm); 61857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org 618649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Push return address (accessible to GC through exit frame pc). 61874acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org // Note that using pc with str is deprecated. 6188b645116853c677aca8a316381b87441ba6004f67danno@chromium.org Label start; 6189b645116853c677aca8a316381b87441ba6004f67danno@chromium.org __ bind(&start); 6190b645116853c677aca8a316381b87441ba6004f67danno@chromium.org __ add(ip, pc, Operand(Assembler::kInstrSize)); 61914acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org __ str(ip, MemOperand(sp, 0)); 619249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ Jump(target); // Call the C++ function. 6193b645116853c677aca8a316381b87441ba6004f67danno@chromium.org ASSERT_EQ(Assembler::kInstrSize + Assembler::kPcLoadDelta, 6194b645116853c677aca8a316381b87441ba6004f67danno@chromium.org masm->SizeOfCodeGeneratedSince(&start)); 6195e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org __ VFPEnsureFPSCRState(r2); 619649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org} 619749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 619849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 6199750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 6200750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Label* miss, 6201750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Label* done, 6202750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register receiver, 6203750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register properties, 6204750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Handle<Name> name, 6205750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register scratch0) { 6206750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ASSERT(name->IsUniqueName()); 6207394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // If names of slots in range from 1 to kProbes - 1 for the hash value are 6208394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // not equal to the name and kProbes-th slot is not used (its name is the 6209394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // undefined value), it guarantees the hash table doesn't contain the 6210394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // property. It's true even if some slots represent deleted properties 6211967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org // (their names are the hole value). 6212394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com for (int i = 0; i < kInlinedProbes; i++) { 6213394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // scratch0 points to properties hash. 6214394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // Compute the masked index: (hash + i + i * i) & mask. 6215394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com Register index = scratch0; 6216394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // Capacity is smi 2^n. 6217394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ ldr(index, FieldMemOperand(properties, kCapacityOffset)); 6218394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ sub(index, index, Operand(1)); 6219394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ and_(index, index, Operand( 6220750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i)))); 6221394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6222394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // Scale the index by multiplying by the entry size. 6223750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ASSERT(NameDictionary::kEntrySize == 3); 6224394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ add(index, index, Operand(index, LSL, 1)); // index *= 3. 6225394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6226394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com Register entity_name = scratch0; 6227394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // Having undefined at this place means the name is not contained. 6228394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com ASSERT_EQ(kSmiTagSize, 1); 6229394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com Register tmp = properties; 6230394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ add(tmp, properties, Operand(index, LSL, 1)); 6231394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 6232394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6233394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com ASSERT(!tmp.is(entity_name)); 6234394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 6235394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ cmp(entity_name, tmp); 6236394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ b(eq, done); 6237394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 623877802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org // Load the hole ready for use below: 623977802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); 624077802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org 624177802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org // Stop if found the property. 624277802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ cmp(entity_name, Operand(Handle<Name>(name))); 624377802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ b(eq, miss); 624477802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org 624577802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org Label good; 624677802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ cmp(entity_name, tmp); 624777802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ b(eq, &good); 624877802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org 624977802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org // Check if the entry name is not a unique name. 625077802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 625177802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ ldrb(entity_name, 625277802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 62531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ JumpIfNotUniqueName(entity_name, miss); 625477802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ bind(&good); 625577802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org 625677802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org // Restore the properties. 625777802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org __ ldr(properties, 625877802e8a4063b935643c0ea6c2957129ddd65039ulan@chromium.org FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 6259394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com } 6260394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6261394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com const int spill_mask = 6262394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() | 6263394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com r2.bit() | r1.bit() | r0.bit()); 6264394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6265394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ stm(db_w, sp, spill_mask); 6266394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 6267750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ mov(r1, Operand(Handle<Name>(name))); 6268750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org NameDictionaryLookupStub stub(NEGATIVE_LOOKUP); 6269394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ CallStub(&stub); 627059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(r0, Operand::Zero()); 6271394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ ldm(ia_w, sp, spill_mask); 6272394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6273394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ b(eq, done); 6274394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com __ b(ne, miss); 6275394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com} 6276394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6277394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com 6278750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Probe the name dictionary in the |elements| register. Jump to the 62791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// |done| label if a property with the given name is found. Jump to 62801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// the |miss| label otherwise. 62811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org// If lookup was successful |scratch2| will be equal to elements + 4 * index. 6282750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, 6283750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Label* miss, 6284750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Label* done, 6285750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register elements, 6286750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register name, 6287750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register scratch1, 6288750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Register scratch2) { 62896e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com ASSERT(!elements.is(scratch1)); 62906e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com ASSERT(!elements.is(scratch2)); 62916e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com ASSERT(!name.is(scratch1)); 62926e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com ASSERT(!name.is(scratch2)); 62936e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com 6294750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ AssertName(name); 62951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 62961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compute the capacity mask. 62971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); 6298bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(scratch1); 62991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ sub(scratch1, scratch1, Operand(1)); 63001c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Generate an unrolled loop that performs a few probes before 63021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // giving up. Measurements done on Gmail indicate that 2 probes 63031c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // cover ~93% of loads from dictionaries. 63041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org for (int i = 0; i < kInlinedProbes; i++) { 63051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 6306750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset)); 63071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (i > 0) { 63081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Add the probe offset (i + i * i) left shifted to avoid right shifting 63091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // the hash in a separate instruction. The value hash + i + i * i is right 63101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // shifted in the following and instruction. 6311750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ASSERT(NameDictionary::GetProbeOffset(i) < 6312750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 1 << (32 - Name::kHashFieldOffset)); 63131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(scratch2, scratch2, Operand( 6314750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 63151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 6316750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ and_(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift)); 63171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Scale the index by multiplying by the element size. 6319750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ASSERT(NameDictionary::kEntrySize == 3); 63201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // scratch2 = scratch2 * 3. 63211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); 63221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Check if the key is identical to the name. 63241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(scratch2, elements, Operand(scratch2, LSL, 2)); 63251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); 63261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ cmp(name, Operand(ip)); 63271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(eq, done); 63281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 63291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org const int spill_mask = 63311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org (lr.bit() | r6.bit() | r5.bit() | r4.bit() | 63321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org r3.bit() | r2.bit() | r1.bit() | r0.bit()) & 63331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org ~(scratch1.bit() | scratch2.bit()); 63341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ stm(db_w, sp, spill_mask); 63366e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com if (name.is(r0)) { 63376e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com ASSERT(!elements.is(r1)); 63386e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com __ Move(r1, name); 63396e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com __ Move(r0, elements); 63406e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com } else { 63416e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com __ Move(r0, elements); 63426e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com __ Move(r1, name); 63436e28b5694dd5a29d2f37d56d5a005e7cfdd952d1erik.corry@gmail.com } 6344750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org NameDictionaryLookupStub stub(POSITIVE_LOOKUP); 63451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ CallStub(&stub); 634659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ cmp(r0, Operand::Zero()); 63471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(scratch2, Operand(r2)); 63481c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldm(ia_w, sp, spill_mask); 63491c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(ne, done); 63511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(eq, miss); 63521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org} 63531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63541c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 6355750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.orgvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 6356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // This stub overrides SometimesSetsUpAFrame() to return false. That means 6357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // we cannot call anything that could cause a GC from this stub. 63581c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Registers: 6359750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // result: NameDictionary to probe 63601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // r1: key 6361750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // dictionary: NameDictionary to probe. 6362750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // index: will hold an index of entry if lookup is successful. 6363750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // might alias with result_. 63641c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Returns: 63651c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // result_ is zero if lookup failed, non zero otherwise. 63661c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register result = r0; 63681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register dictionary = r0; 63691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register key = r1; 63701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register index = r2; 63711c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register mask = r3; 63721c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register hash = r4; 63731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register undefined = r5; 63741c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Register entry_key = r6; 63751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63761c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 63771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(mask, FieldMemOperand(dictionary, kCapacityOffset)); 6379bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ SmiUntag(mask); 63801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ sub(mask, mask, Operand(1)); 63811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 6382750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 63831c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63841c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 63851c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 63861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org for (int i = kInlinedProbes; i < kTotalProbes; i++) { 63871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Compute the masked index: (hash + i + i * i) & mask. 63881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Capacity is smi 2^n. 63891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (i > 0) { 63901c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Add the probe offset (i + i * i) left shifted to avoid right shifting 63911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // the hash in a separate instruction. The value hash + i + i * i is right 63921c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // shifted in the following and instruction. 6393750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ASSERT(NameDictionary::GetProbeOffset(i) < 6394750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org 1 << (32 - Name::kHashFieldOffset)); 63951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(index, hash, Operand( 6396750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 63971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } else { 63981c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(index, Operand(hash)); 63991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 6400750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ and_(index, mask, Operand(index, LSR, Name::kHashShift)); 64011c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64021c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Scale the index by multiplying by the entry size. 6403750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org ASSERT(NameDictionary::kEntrySize == 3); 64041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(index, index, Operand(index, LSL, 1)); // index *= 3. 64051c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org ASSERT_EQ(kSmiTagSize, 1); 64071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ add(index, dictionary, Operand(index, LSL, 2)); 64081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset)); 64091c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Having undefined at this place means the name is not contained. 64111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ cmp(entry_key, Operand(undefined)); 64121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(eq, ¬_in_dictionary); 64131c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Stop if found the property. 64151c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ cmp(entry_key, Operand(key)); 64161c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ b(eq, &in_dictionary); 64171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64181c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 6419750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // Check if the entry name is not a unique name. 64201c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 64211c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ ldrb(entry_key, 64221c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 64231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary); 64241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 64251c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 64261c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&maybe_in_dictionary); 64281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // If we are doing negative lookup then probing failure should be 64291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // treated as a lookup success. For positive lookup probing failure 64301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // should be treated as lookup failure. 64311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (mode_ == POSITIVE_LOOKUP) { 6432ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ mov(result, Operand::Zero()); 64331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(); 64341c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 64351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64361c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(&in_dictionary); 64371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ mov(result, Operand(1)); 64381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(); 64391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ bind(¬_in_dictionary); 6441ddd545c4c343dcf4331b9d80d2a0bdfa373a4a0fricow@chromium.org __ mov(result, Operand::Zero()); 64421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org __ Ret(); 64431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org} 64441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 64451c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 6446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstruct AheadOfTimeWriteBarrierStubList { 6447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Register object, value, address; 6448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RememberedSetAction action; 6449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}; 6450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6451e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 64521456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#define REG(Name) { kRegister_ ## Name ## _Code } 6453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 64541456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgstatic const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { 6455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Used in RegExpExecStub. 64561456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, 6457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Used in CompileArrayPushCall. 6458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. 6459c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Also used in KeyedStoreIC::GenerateGeneric. 64601456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, 6461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Used in CompileStoreGlobal. 64621456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET }, 6463c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. 64641456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, 64651456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, 6466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. 64671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r2), REG(r1), REG(r3), EMIT_REMEMBERED_SET }, 64681456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r3), REG(r1), REG(r2), EMIT_REMEMBERED_SET }, 6469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // KeyedStoreStubCompiler::GenerateStoreFastElement. 64701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r3), REG(r2), REG(r4), EMIT_REMEMBERED_SET }, 64711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r2), REG(r3), REG(r4), EMIT_REMEMBERED_SET }, 6472830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org // ElementsTransitionGenerator::GenerateMapChangeElementTransition 6473830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org // and ElementsTransitionGenerator::GenerateSmiToDouble 6474394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // and ElementsTransitionGenerator::GenerateDoubleToObject 64751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r2), REG(r3), REG(r9), EMIT_REMEMBERED_SET }, 64761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r2), REG(r3), REG(r9), OMIT_REMEMBERED_SET }, 6477394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com // ElementsTransitionGenerator::GenerateDoubleToObject 64781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r6), REG(r2), REG(r0), EMIT_REMEMBERED_SET }, 64791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r2), REG(r6), REG(r9), EMIT_REMEMBERED_SET }, 648004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // StoreArrayLiteralElementStub::Generate 64811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET }, 64825a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org // FastNewClosureStub::Generate 64835a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET }, 648457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org // StringAddStub::Generate 648557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org { REG(r7), REG(r1), REG(r4), EMIT_REMEMBERED_SET }, 648657ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org { REG(r7), REG(r0), REG(r4), EMIT_REMEMBERED_SET }, 6487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Null termination. 64881456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} 6489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}; 6490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 64911456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org#undef REG 6492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 649333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool RecordWriteStub::IsPregenerated() { 64951456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; 6496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com !entry->object.is(no_reg); 6497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com entry++) { 6498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (object_.is(entry->object) && 6499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com value_.is(entry->value) && 6500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com address_.is(entry->address) && 6501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com remembered_set_action_ == entry->action && 6502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com save_fp_regs_mode_ == kDontSaveFPRegs) { 6503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com return true; 6504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com return false; 6507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 65108432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 65118432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org Isolate* isolate) { 6512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com StoreBufferOverflowStub stub1(kDontSaveFPRegs); 65138432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org stub1.GetCode(isolate)->set_is_pregenerated(true); 651477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org // Hydrogen code stubs need stub2 at snapshot time. 651577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org StoreBufferOverflowStub stub2(kSaveFPRegs); 651677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org stub2.GetCode(isolate)->set_is_pregenerated(true); 6517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 65208432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.orgvoid RecordWriteStub::GenerateFixedRegStubsAheadOfTime(Isolate* isolate) { 65211456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; 6522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com !entry->object.is(no_reg); 6523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com entry++) { 6524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RecordWriteStub stub(entry->object, 6525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com entry->value, 6526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com entry->address, 6527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com entry->action, 6528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com kDontSaveFPRegs); 65298432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org stub.GetCode(isolate)->set_is_pregenerated(true); 6530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6532c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 653433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgbool CodeStub::CanUseFPRegisters() { 6535e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org return true; // VFP2 is a base requirement for V8 653633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org} 653733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 653833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Takes the input in 3 registers: address_ value_ and object_. A pointer to 6540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// the value has just been written into the object, now this stub makes sure 6541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// we keep the GC informed. The word in the object where the value has been 6542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// written is in the address register. 6543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::Generate(MacroAssembler* masm) { 6544c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label skip_to_incremental_noncompacting; 6545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label skip_to_incremental_compacting; 6546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // The first two instructions are generated with labels so as to get the 6548c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // offset fixed up correctly by the bind(Label*) call. We patch it back and 6549c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // forth between a compare instructions (a nop in this position) and the 6550c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // real branch when we start and stop incremental heap marking. 6551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // See RecordWriteStub::Patch for details. 65527028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org { 65537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // Block literal pool emission, as the position of these two instructions 65547028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org // is assumed by the patching code. 65557028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org Assembler::BlockConstPoolScope block_const_pool(masm); 65567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org __ b(&skip_to_incremental_noncompacting); 65577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org __ b(&skip_to_incremental_compacting); 65587028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org } 6559c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6560c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 6561c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ RememberedSetHelper(object_, 6562c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com address_, 6563c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com value_, 6564c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com save_fp_regs_mode_, 6565c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MacroAssembler::kReturnAtEnd); 6566c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6567c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Ret(); 6568c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6569c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&skip_to_incremental_noncompacting); 6570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com GenerateIncremental(masm, INCREMENTAL); 6571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6572c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&skip_to_incremental_compacting); 6573c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com GenerateIncremental(masm, INCREMENTAL_COMPACTION); 6574c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6575c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 6576c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Will be checked in IncrementalMarking::ActivateGeneratedStub. 6577c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT(Assembler::GetBranchOffset(masm->instr_at(0)) < (1 << 12)); 6578c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT(Assembler::GetBranchOffset(masm->instr_at(4)) < (1 << 12)); 6579c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com PatchBranchIntoNop(masm, 0); 6580c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com PatchBranchIntoNop(masm, Assembler::kInstrSize); 6581c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6582c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6583c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6584c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 6585c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.Save(masm); 6586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 6588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label dont_need_remembered_set; 6589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6590c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); 6591c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 6592c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.scratch0(), 6593c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com &dont_need_remembered_set); 6594c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6595c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CheckPageFlag(regs_.object(), 6596c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.scratch0(), 6597c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1 << MemoryChunk::SCAN_ON_SCAVENGE, 6598c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ne, 6599c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com &dont_need_remembered_set); 6600c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6601c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // First notify the incremental marker if necessary, then update the 6602c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // remembered set. 6603c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com CheckNeedsToInformIncrementalMarker( 6604c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); 6605c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com InformIncrementalMarker(masm, mode); 6606c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.Restore(masm); 6607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ RememberedSetHelper(object_, 6608c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com address_, 6609c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com value_, 6610c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com save_fp_regs_mode_, 6611c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MacroAssembler::kReturnAtEnd); 6612c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6613c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&dont_need_remembered_set); 6614c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6615c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6616c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com CheckNeedsToInformIncrementalMarker( 6617c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 6618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com InformIncrementalMarker(masm, mode); 6619c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.Restore(masm); 6620c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Ret(); 6621c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6622c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6623c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6624c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { 6625c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); 6626c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com int argument_count = 3; 6627c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ PrepareCallCFunction(argument_count, regs_.scratch0()); 6628c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Register address = 6629c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com r0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 6630c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT(!address.is(regs_.object())); 6631c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT(!address.is(r0)); 6632c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Move(address, regs_.address()); 6633c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Move(r0, regs_.object()); 66348e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org __ Move(r1, address); 663532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org __ mov(r2, Operand(ExternalReference::isolate_address(masm->isolate()))); 6636c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com AllowExternalCallThatCantCauseGC scope(masm); 6638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (mode == INCREMENTAL_COMPACTION) { 6639c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallCFunction( 6640c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::incremental_evacuation_record_write_function( 6641c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm->isolate()), 6642c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com argument_count); 6643c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 6644c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT(mode == INCREMENTAL); 6645c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallCFunction( 6646c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::incremental_marking_record_write_function( 6647c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm->isolate()), 6648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com argument_count); 6649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); 6651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6652c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6653c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker( 6655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MacroAssembler* masm, 6656c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com OnNoNeedToInformIncrementalMarker on_no_need, 6657c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Mode mode) { 6658c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label on_black; 6659c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label need_incremental; 6660c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label need_incremental_pop_scratch; 6661c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 666233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ and_(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); 666333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ ldr(regs_.scratch1(), 666433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org MemOperand(regs_.scratch0(), 666533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org MemoryChunk::kWriteBarrierCounterOffset)); 666633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ sub(regs_.scratch1(), regs_.scratch1(), Operand(1), SetCC); 666733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ str(regs_.scratch1(), 666833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org MemOperand(regs_.scratch0(), 666933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org MemoryChunk::kWriteBarrierCounterOffset)); 667033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org __ b(mi, &need_incremental); 667133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6672c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Let's look at the color of the object: If it is not black we don't have 6673c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // to inform the incremental marker. 6674c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 6675c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6676c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.Restore(masm); 6677c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 6678c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ RememberedSetHelper(object_, 6679c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com address_, 6680c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com value_, 6681c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com save_fp_regs_mode_, 6682c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MacroAssembler::kReturnAtEnd); 6683c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 6684c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Ret(); 6685c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6686c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6687c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&on_black); 6688c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6689c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the value from the slot. 6690c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); 6691c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6692c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (mode == INCREMENTAL_COMPACTION) { 6693c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label ensure_not_white; 6694c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6695c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CheckPageFlag(regs_.scratch0(), // Contains value. 6696c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.scratch1(), // Scratch. 6697c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MemoryChunk::kEvacuationCandidateMask, 6698c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com eq, 6699c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com &ensure_not_white); 6700c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6701c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CheckPageFlag(regs_.object(), 6702c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.scratch1(), // Scratch. 6703c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MemoryChunk::kSkipEvacuationSlotsRecordingMask, 6704c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com eq, 6705c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com &need_incremental); 6706c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6707c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&ensure_not_white); 6708c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6709c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6710c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // We need extra registers for this, so we push the object and the address 6711c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // register temporarily. 6712c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Push(regs_.object(), regs_.address()); 6713c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ EnsureNotWhite(regs_.scratch0(), // The value. 6714c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.scratch1(), // Scratch. 6715c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.object(), // Scratch. 6716c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.address(), // Scratch. 6717c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com &need_incremental_pop_scratch); 6718c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Pop(regs_.object(), regs_.address()); 6719c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6720c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com regs_.Restore(masm); 6721c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 6722c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ RememberedSetHelper(object_, 6723c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com address_, 6724c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com value_, 6725c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com save_fp_regs_mode_, 6726c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MacroAssembler::kReturnAtEnd); 6727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 6728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Ret(); 6729c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6730c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6731c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&need_incremental_pop_scratch); 6732c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Pop(regs_.object(), regs_.address()); 6733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6734c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&need_incremental); 6735c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 6736c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Fall through when we need to inform the incremental marker. 6737c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} 6738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 673904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 674004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.orgvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 674104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // ----------- S t a t e ------------- 674204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // -- r0 : element value to store 674304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // -- r3 : element index as smi 6744b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org // -- sp[0] : array literal index in function as smi 6745b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org // -- sp[4] : array literal 6746b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org // clobbers r1, r2, r4 674704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // ----------------------------------- 674804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 674904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org Label element_done; 675004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org Label double_elements; 675104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org Label smi_element; 675204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org Label slow_elements; 675304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org Label fast_elements; 675404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 6755b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org // Get array literal index, array literal and its map. 6756b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org __ ldr(r4, MemOperand(sp, 0 * kPointerSize)); 6757b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 6758b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset)); 6759b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org 676004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ CheckFastElements(r2, r5, &double_elements); 6761830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS 676204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ JumpIfSmi(r0, &smi_element); 6763830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org __ CheckFastSmiElements(r2, r5, &fast_elements); 676404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 676504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // Store into the array literal requires a elements transition. Call into 676604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // the runtime. 676704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ bind(&slow_elements); 676804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // call. 676904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ Push(r1, r3, r0); 677004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 677104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset)); 677204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ Push(r5, r4); 677304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 677404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 6775830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object. 677604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ bind(&fast_elements); 677704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); 6778bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3)); 677904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 678004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ str(r0, MemOperand(r6, 0)); 678104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // Update the write barrier for the array store. 678204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs, 678304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 678404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ Ret(); 678504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 6786830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS, 6787830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org // and value is Smi. 678804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ bind(&smi_element); 678904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); 6790bf9432e3965b385e2e8df3701b710c105f5b3eb7ulan@chromium.org __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3)); 679104e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize)); 679204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ Ret(); 679304e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 679404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. 679504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ bind(&double_elements); 679604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); 6797fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org __ StoreNumberToDoubleElements(r0, r3, r5, r6, d0, &slow_elements); 679804e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org __ Ret(); 679904e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org} 680004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org 6801753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6802068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.orgvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 6803e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); 68048432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); 68052f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org int parameter_count_offset = 68062f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 68072f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org __ ldr(r1, MemOperand(fp, parameter_count_offset)); 6808f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org if (function_mode_ == JS_FUNCTION_STUB_MODE) { 6809f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ add(r1, r1, Operand(1)); 6810f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org } 6811068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 68122f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org __ mov(r1, Operand(r1, LSL, kPointerSizeLog2)); 68132f0efdebb142c00de6950453b4c2df20ceb8df6emmassi@chromium.org __ add(sp, sp, r1); 6814068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org __ Ret(); 6815068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org} 6816068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org 6817068ea0a6ea115c058d1d9798029bd7fa1eaaa955mstarzinger@chromium.org 6818753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.orgvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 68191510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (masm->isolate()->function_entry_hook() != NULL) { 68208e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize); 68211510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org AllowStubCallsScope allow_stub_calls(masm, true); 6822753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org ProfileEntryHookStub stub; 6823753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ push(lr); 6824753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ CallStub(&stub); 6825753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ pop(lr); 6826753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org } 6827753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org} 6828753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6829753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6830753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.orgvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) { 6831753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // The entry hook is a "push lr" instruction, followed by a call. 6832753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org const int32_t kReturnAddressDistanceFromFunctionStart = 683389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org 3 * Assembler::kInstrSize; 6834753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 68351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // This should contain all kCallerSaved registers. 68361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org const RegList kSavedRegs = 68371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1 << 0 | // r0 68381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1 << 1 | // r1 68391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1 << 2 | // r2 68401510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1 << 3 | // r3 68411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1 << 5 | // r5 68421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 1 << 9; // r9 68431510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // We also save lr, so the count here is one higher than the mask indicates. 68441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org const int32_t kNumSavedRegs = 7; 68451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 68461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ASSERT((kCallerSaved & kSavedRegs) == kCallerSaved); 68471510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 68481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Save all caller-save registers as this may be called from anywhere. 68491510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ stm(db_w, sp, kSavedRegs | lr.bit()); 6850753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6851753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // Compute the function's address for the first argument. 6852753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ sub(r0, lr, Operand(kReturnAddressDistanceFromFunctionStart)); 6853753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6854753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // The caller's return address is above the saved temporaries. 6855753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // Grab that for the second argument to the hook. 6856753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ add(r1, sp, Operand(kNumSavedRegs * kPointerSize)); 6857753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6858753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // Align the stack if necessary. 6859753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org int frame_alignment = masm->ActivationFrameAlignment(); 6860753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org if (frame_alignment > kPointerSize) { 6861753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ mov(r5, sp); 6862753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org ASSERT(IsPowerOf2(frame_alignment)); 6863753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ and_(sp, sp, Operand(-frame_alignment)); 6864753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org } 6865753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 686693a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_HOST_ARCH_ARM 68671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org int32_t entry_hook = 68681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook()); 68691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ mov(ip, Operand(entry_hook)); 6870753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org#else 6871753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // Under the simulator we need to indirect the entry hook through a 6872753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // trampoline function at a known address. 68731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); 6874753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ mov(ip, Operand(ExternalReference(&dispatcher, 6875753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org ExternalReference::BUILTIN_CALL, 6876753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org masm->isolate()))); 6877753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org#endif 6878753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ Call(ip); 6879753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6880753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org // Restore the stack pointer if needed. 6881753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org if (frame_alignment > kPointerSize) { 6882753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org __ mov(sp, r5); 6883753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org } 6884753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 68851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Also pop pc to get Ret(0). 68861510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ ldm(ia_w, sp, kSavedRegs | pc.bit()); 6887753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org} 6888753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org 6889ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6890ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgtemplate<class T> 6891ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void CreateArrayDispatch(MacroAssembler* masm) { 6892ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org int last_index = GetSequenceIndexFromFastElementsKind( 6893ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 6894ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org for (int i = 0; i <= last_index; ++i) { 6895ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org Label next; 6896ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 6897ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ cmp(r3, Operand(kind)); 6898ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ b(ne, &next); 6899ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org T stub(kind); 6900ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ TailCallStub(&stub); 6901ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ bind(&next); 6902ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } 6903ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6904ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // If we reached this point there is a problem. 6905594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kUnexpectedElementsKindInArrayConstructor); 6906ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org} 6907ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6908ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6909ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm) { 6910ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // r2 - type info cell 6911ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // r3 - kind 6912ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // r0 - number of arguments 6913ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // r1 - constructor? 6914ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // sp[0] - last argument 6915ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ASSERT(FAST_SMI_ELEMENTS == 0); 6916ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 6917ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ASSERT(FAST_ELEMENTS == 2); 6918ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ASSERT(FAST_HOLEY_ELEMENTS == 3); 6919ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ASSERT(FAST_DOUBLE_ELEMENTS == 4); 6920ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 6921ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6922ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // is the low bit set? If so, we are holey and that is good. 6923ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ tst(r3, Operand(1)); 6924ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org Label normal_sequence; 6925ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ b(ne, &normal_sequence); 6926ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6927ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // look at the first argument 6928ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ ldr(r5, MemOperand(sp, 0)); 6929ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ cmp(r5, Operand::Zero()); 6930ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ b(eq, &normal_sequence); 6931ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6932ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // We are going to create a holey array, but our kind is non-holey. 6933bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Fix kind and retry (only if we have an allocation site in the cell). 6934ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ add(r3, r3, Operand(1)); 6935bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); 6936ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ b(eq, &normal_sequence); 6937bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset)); 6938bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ ldr(r5, FieldMemOperand(r5, 0)); 6939bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); 6940bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ b(ne, &normal_sequence); 69411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 6942ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // Save the resulting elements kind in type info 6943ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ SmiTag(r3); 6944bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset)); 6945bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ str(r3, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 6946ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ SmiUntag(r3); 6947ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6948ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ bind(&normal_sequence); 6949ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org int last_index = GetSequenceIndexFromFastElementsKind( 6950ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 6951ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org for (int i = 0; i <= last_index; ++i) { 6952ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org Label next; 6953ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 6954ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ cmp(r3, Operand(kind)); 6955ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ b(ne, &next); 6956ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ArraySingleArgumentConstructorStub stub(kind); 6957ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ TailCallStub(&stub); 6958ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ bind(&next); 6959ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } 6960ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6961ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // If we reached this point there is a problem. 6962594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kUnexpectedElementsKindInArrayConstructor); 6963ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org} 6964ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6965ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6966ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgtemplate<class T> 6967ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 6968ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org int to_index = GetSequenceIndexFromFastElementsKind( 6969ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org TERMINAL_FAST_ELEMENTS_KIND); 6970ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org for (int i = 0; i <= to_index; ++i) { 6971ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 6972ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org T stub(kind); 6973ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org stub.GetCode(isolate)->set_is_pregenerated(true); 6974bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 69751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); 6976d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org stub1.GetCode(isolate)->set_is_pregenerated(true); 6977d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 6978ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } 6979ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org} 6980ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6981ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6982ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 6983ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 6984ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org isolate); 6985ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 6986ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org isolate); 6987ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( 6988ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org isolate); 6989ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org} 6990ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6991ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 6992d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( 6993d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Isolate* isolate) { 6994d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; 6995d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org for (int i = 0; i < 2; i++) { 6996d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // For internal arrays we only need a few things 6997d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); 6998d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org stubh1.GetCode(isolate)->set_is_pregenerated(true); 6999d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); 7000d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org stubh2.GetCode(isolate)->set_is_pregenerated(true); 7001d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); 7002d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org stubh3.GetCode(isolate)->set_is_pregenerated(true); 7003d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 7004d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 7005d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7006d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7007ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid ArrayConstructorStub::Generate(MacroAssembler* masm) { 7008ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // ----------- S t a t e ------------- 7009ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // -- r0 : argc (only if argument_count_ == ANY) 7010ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // -- r1 : constructor 7011ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // -- r2 : type info cell 7012ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // -- sp[0] : return address 7013ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // -- sp[4] : last argument 7014ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // ----------------------------------- 7015ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org if (FLAG_debug_code) { 7016ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // The array construct code is only set for the global and natives 7017ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // builtin Array functions which always have maps. 7018ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 7019ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // Initial map for the builtin Array function should be a map. 7020ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 7021ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org // Will both indicate a NULL and a Smi. 7022ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ tst(r3, Operand(kSmiTagMask)); 7023594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(ne, kUnexpectedInitialMapForArrayFunction); 7024ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ CompareObjectType(r3, r3, r4, MAP_TYPE); 7025594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 7026ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 702741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org // We should either have undefined in ebx or a valid cell 7028ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org Label okay_here; 702941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); 7030bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); 7031ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ b(eq, &okay_here); 7032ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ ldr(r3, FieldMemOperand(r2, 0)); 703341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org __ cmp(r3, Operand(cell_map)); 7034594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kExpectedPropertyCellInRegisterEbx); 7035ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org __ bind(&okay_here); 7036ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } 7037ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 70381510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Label no_info, switch_ready; 70391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Get the elements kind and case on that. 7040bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); 70411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ b(eq, &no_info); 70421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); 7043bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 7044bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // The type cell may have undefined in its value. 7045bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); 7046bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ b(eq, &no_info); 7047bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 7048bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // The type cell has either an AllocationSite or a JSFunction 7049bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ ldr(r4, FieldMemOperand(r3, 0)); 7050bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex); 7051bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ b(ne, &no_info); 7052bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 7053bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org __ ldr(r3, FieldMemOperand(r3, AllocationSite::kTransitionInfoOffset)); 70541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ SmiUntag(r3); 70551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ jmp(&switch_ready); 70561510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ bind(&no_info); 70571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ mov(r3, Operand(GetInitialFastElementsKind())); 70581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ bind(&switch_ready); 70591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 70601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (argument_count_ == ANY) { 70611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Label not_zero_case, not_one_case; 70621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ tst(r0, r0); 70631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ b(ne, ¬_zero_case); 70641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 70651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 70661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ bind(¬_zero_case); 70671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ cmp(r0, Operand(1)); 70681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ b(gt, ¬_one_case); 70691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org CreateArrayDispatchOneArgument(masm); 70701510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 70711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ bind(¬_one_case); 70721510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 70731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } else if (argument_count_ == NONE) { 70741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); 70751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } else if (argument_count_ == ONE) { 70761510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org CreateArrayDispatchOneArgument(masm); 70771510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } else if (argument_count_ == MORE_THAN_ONE) { 70781510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); 7079ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } else { 70801510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org UNREACHABLE(); 7081ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org } 7082ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org} 7083ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 7084ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org 7085d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStub::GenerateCase( 7086d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org MacroAssembler* masm, ElementsKind kind) { 7087d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Label not_zero_case, not_one_case; 7088d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Label normal_sequence; 7089d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7090d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ tst(r0, r0); 7091d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ b(ne, ¬_zero_case); 7092d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArrayNoArgumentConstructorStub stub0(kind); 7093d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ TailCallStub(&stub0); 7094d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7095d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ bind(¬_zero_case); 7096d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ cmp(r0, Operand(1)); 7097d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ b(gt, ¬_one_case); 7098d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7099d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org if (IsFastPackedElementsKind(kind)) { 7100d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // We might need to create a holey array 7101d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // look at the first argument 7102d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ ldr(r3, MemOperand(sp, 0)); 7103d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ cmp(r3, Operand::Zero()); 7104d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ b(eq, &normal_sequence); 7105d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7106d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArraySingleArgumentConstructorStub 7107d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org stub1_holey(GetHoleyElementsKind(kind)); 7108d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ TailCallStub(&stub1_holey); 7109d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 7110d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7111d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ bind(&normal_sequence); 7112d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArraySingleArgumentConstructorStub stub1(kind); 7113d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ TailCallStub(&stub1); 7114d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7115d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ bind(¬_one_case); 7116d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org InternalArrayNArgumentsConstructorStub stubN(kind); 7117d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ TailCallStub(&stubN); 7118d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 7119d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7120d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7121d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 7122d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // ----------- S t a t e ------------- 7123d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // -- r0 : argc 7124d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // -- r1 : constructor 7125d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // -- sp[0] : return address 7126d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // -- sp[4] : last argument 7127d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // ----------------------------------- 7128d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7129d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org if (FLAG_debug_code) { 7130d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // The array construct code is only set for the global and natives 7131d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // builtin Array functions which always have maps. 7132d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7133d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // Initial map for the builtin Array function should be a map. 7134d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 7135d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org // Will both indicate a NULL and a Smi. 7136d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ tst(r3, Operand(kSmiTagMask)); 7137594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(ne, kUnexpectedInitialMapForArrayFunction); 7138d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ CompareObjectType(r3, r3, r4, MAP_TYPE); 7139594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 7140d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org } 7141d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 71421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Figure out the right elements kind 71431510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 71441510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Load the map's "bit field 2" into |result|. We only need the first byte, 71451510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // but the following bit field extraction takes care of that anyway. 71461510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset)); 71471510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Retrieve elements_kind from bit field 2. 71481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ Ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount); 7149d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 71501510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org if (FLAG_debug_code) { 71511510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Label done; 7152d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org __ cmp(r3, Operand(FAST_ELEMENTS)); 71531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ b(eq, &done); 71541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS)); 71551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ Assert(eq, 7156594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org kInvalidElementsKindForInternalArrayOrInternalPackedArray); 71571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ bind(&done); 71581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org } 7159d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 71601510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Label fast_elements_case; 71611510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ cmp(r3, Operand(FAST_ELEMENTS)); 71621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ b(eq, &fast_elements_case); 71631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org GenerateCase(masm, FAST_HOLEY_ELEMENTS); 7164d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 71651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ bind(&fast_elements_case); 71661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org GenerateCase(masm, FAST_ELEMENTS); 7167d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org} 7168d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 7169d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org 717065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#undef __ 717165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 717265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org} } // namespace v8::internal 717365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org 717465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org#endif // V8_TARGET_ARCH_ARM 7175