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