1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "api.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arguments.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "builtins.h" 34b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "gdb-jit.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h" 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkenamespace { 42e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Arguments object passed to C++ builtins. 44e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketemplate <BuiltinExtraArguments extra_args> 45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeclass BuiltinArguments : public Arguments { 46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke public: 47e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BuiltinArguments(int length, Object** arguments) 48e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke : Arguments(length, arguments) { } 49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Object*& operator[] (int index) { 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(index < length()); 52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Arguments::operator[](index); 53e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 54e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 55e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke template <class S> Handle<S> at(int index) { 56e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(index < length()); 57e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Arguments::at<S>(index); 58e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<Object> receiver() { 61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Arguments::at<Object>(0); 62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<JSFunction> called_function() { 65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION); 66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Arguments::at<JSFunction>(Arguments::length() - 1); 67e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 68e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 69e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Gets the total number of arguments including the receiver (but 70e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // excluding extra arguments). 71e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int length() const { 72e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 73e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Arguments::length(); 74e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 75e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 76e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG 77e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void Verify() { 78e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check we have at least the receiver. 79e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(Arguments::length() >= 1); 80e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 81e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif 82e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}; 83e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 84e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 85e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Specialize BuiltinArguments for the called function extra argument. 86e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 87e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketemplate <> 88e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkeint BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const { 89e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return Arguments::length() - 1; 90e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 91e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 92e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG 93e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketemplate <> 94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() { 95e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Check we have at least the receiver and the called function. 96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT(Arguments::length() >= 2); 97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Make sure cast to JSFunction succeeds. 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke called_function(); 99e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 100e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif 101e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#define DEF_ARG_TYPE(name, spec) \ 104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke typedef BuiltinArguments<spec> name##ArgumentsType; 105e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeBUILTIN_LIST_C(DEF_ARG_TYPE) 106e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#undef DEF_ARG_TYPE 107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} // namespace 109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 111e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Support macro for defining builtins in C++. 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A builtin function is defined by writing: 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// BUILTIN(name) { 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ... 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// } 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 120e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// In the body of the builtin function the arguments can be accessed 121e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// through the BuiltinArguments object args. 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define BUILTIN(name) \ 12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block name##ArgumentsType args, Isolate* isolate); \ 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block MUST_USE_RESULT static MaybeObject* Builtin_##name( \ 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block name##ArgumentsType args, Isolate* isolate) { \ 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate == Isolate::Current()); \ 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block args.Verify(); \ 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Builtin_Impl_##name(args, isolate); \ 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } \ 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ 13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block name##ArgumentsType args, Isolate* isolate) 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#else // For release mode. 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define BUILTIN(name) \ 14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static MaybeObject* Builtin_##name(name##ArgumentsType args, Isolate* isolate) 141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic inline bool CalledAsConstructor(Isolate* isolate) { 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the result using a full stack frame iterator and check 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // that the state of the stack is as we assume it to be in the 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code below. 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackFrameIterator it; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(it.frame()->is_exit()); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block it.Advance(); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackFrame* frame = it.frame(); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool reference_result = frame->is_construct(); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Address fp = Isolate::c_entry_fp(isolate->thread_local_top()); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Because we know fp points to an exit frame we can use the relevant 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // part of ExitFrame::ComputeCallerState directly. 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kCallerOffset = ExitFrameConstants::kCallerFPOffset; 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address caller_fp = Memory::Address_at(fp + kCallerOffset); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This inlines the part of StackFrame::ComputeType that grabs the 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // type of the current frame. Note that StackFrame::ComputeType 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // has been specialized for each architecture so if any one of them 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // changes this code has to be changed as well. 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kMarkerOffset = StandardFrameConstants::kMarkerOffset; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* marker = Memory::Object_at(caller_fp + kMarkerOffset); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool result = (marker == kConstructMarker); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(result, reference_result); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(Illegal) { 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNREACHABLE(); 17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->heap()->undefined_value(); // Make compiler happy. 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(EmptyFunction) { 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->heap()->undefined_value(); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(ArrayCodeGeneric) { 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->counters()->array_function_runtime()->Increment(); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSArray* array; 19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (CalledAsConstructor(isolate)) { 192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke array = JSArray::cast(*args.receiver()); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate the JS Array 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* constructor = 19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->context()->global_context()->array_function(); 1975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); 1995913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block array = JSArray::cast(obj); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'array' now contains the JSArray we should initialize. 2058defd9ff6930b4e24729971a61cf7469daf119beSteve Block ASSERT(array->HasFastElements()); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Optimize the case where there is one argument and the argument is a 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // small smi. 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (args.length() == 2) { 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* obj = args[1]; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (obj->IsSmi()) { 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int len = Smi::cast(obj)->value(); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { 2145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len); 2165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2175913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block array->SetContent(FixedArray::cast(obj)); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return array; 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Take the argument as the length. 2235913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = array->Initialize(0); 2245913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2255913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return array->SetElementsLength(args[1]); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Optimize the case where there are no parameters passed. 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (args.length() == 1) { 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return array->Initialize(JSArray::kPreallocatedArrayElements); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Take the arguments as elements. 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int number_of_elements = args.length() - 1; 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Smi* len = Smi::FromInt(number_of_elements); 2375913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 23844f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len->value()); 2395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2414515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 2424515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke AssertNoAllocation no_gc; 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray* elms = FixedArray::cast(obj); 2444515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill in the content 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int index = 0; index < number_of_elements; index++) { 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elms->set(index, args[index+1], mode); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set length and elements on the array. 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block array->set_elements(FixedArray::cast(obj)); 2524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke array->set_length(len); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return array; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) { 2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSFunction* array_function = 26044f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->isolate()->context()->global_context()->array_function(); 2615913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 26244f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_result = heap->AllocateJSObject(array_function); 2635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 2645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result; 2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 26944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray(Heap* heap) { 2705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_result = AllocateJSArray(heap); 2725913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 2735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* result_array = JSArray::cast(result); 2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array->set_length(Smi::FromInt(0)); 27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block result_array->set_elements(heap->empty_fixed_array()); 2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result_array; 2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 28144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void CopyElements(Heap* heap, 28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AssertNoAllocation* no_gc, 2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* dst, 2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int dst_index, 2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* src, 2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int src_index, 2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len) { 2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(dst != src); // Use MoveElements instead. 28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(dst->map() != HEAP->fixed_cow_array_map()); 2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(len > 0); 2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CopyWords(dst->data_start() + dst_index, 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block src->data_start() + src_index, 2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block len); 2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); 2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode == UPDATE_WRITE_BARRIER) { 29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); 2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 30144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void MoveElements(Heap* heap, 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AssertNoAllocation* no_gc, 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* dst, 3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int dst_index, 3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* src, 3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int src_index, 3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len) { 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(dst->map() != HEAP->fixed_cow_array_map()); 3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block memmove(dst->data_start() + dst_index, 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block src->data_start() + src_index, 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block len * kPointerSize); 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode == UPDATE_WRITE_BARRIER) { 31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 31944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void FillWithHoles(Heap* heap, FixedArray* dst, int from, int to) { 32044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(dst->map() != heap->fixed_cow_array_map()); 32144f0eee88ff00398ff7f715fab053374d808c90dSteve Block MemsetPointer(dst->data_start() + from, heap->the_hole_value(), to - from); 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 32544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic FixedArray* LeftTrimFixedArray(Heap* heap, 32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray* elms, 32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int to_trim) { 32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(elms->map() != HEAP->fixed_cow_array_map()); 329791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // For now this trick is only applied to fixed arrays in new and paged space. 3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // In large object space the object's start must coincide with chunk 3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and thus the trick is just not applicable. 33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!HEAP->lo_space()->Contains(elms)); 3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(FixedArray::kMapOffset == 0); 3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize); 3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(FixedArray::kHeaderSize == 2 * kPointerSize); 3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object** former_start = HeapObject::RawField(elms, 0); 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int len = elms->length(); 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 342791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (to_trim > FixedArray::kHeaderSize / kPointerSize && 34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block !heap->new_space()->Contains(elms)) { 344791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // If we are doing a big trim in old space then we zap the space that was 345791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // formerly part of the array so that the GC (aided by the card-based 346791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // remembered set) won't find pointers to new-space there. 347791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Object** zap = reinterpret_cast<Object**>(elms->address()); 348791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block zap++; // Header of filler must be at least one word so skip that. 349791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block for (int i = 1; i < to_trim; i++) { 350791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block *zap++ = Smi::FromInt(0); 351791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 352791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Technically in new space this write might be omitted (except for 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // debug mode which iterates through the heap), but to play safer 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // we still do it. 35644f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->CreateFillerObjectAt(elms->address(), to_trim * kPointerSize); 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block former_start[to_trim] = heap->fixed_array_map(); 3597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch former_start[to_trim + 1] = Smi::FromInt(len - to_trim); 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 361791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return FixedArray::cast(HeapObject::FromAddress( 362791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block elms->address() + to_trim * kPointerSize)); 3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 36644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic bool ArrayPrototypeHasNoElements(Heap* heap, 36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Context* global_context, 36825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen JSObject* array_proto) { 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This method depends on non writability of Object and Array prototype 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // fields. 37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (array_proto->elements() != heap->empty_fixed_array()) return false; 3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Hidden prototype 37325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen array_proto = JSObject::cast(array_proto->GetPrototype()); 37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(array_proto->elements() == heap->empty_fixed_array()); 3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Object.prototype 3761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Object* proto = array_proto->GetPrototype(); 37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (proto == heap->null_value()) return false; 3781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block array_proto = JSObject::cast(proto); 37925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (array_proto != global_context->initial_object_prototype()) return false; 38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (array_proto->elements() != heap->empty_fixed_array()) return false; 381053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return array_proto->GetPrototype()->IsNull(); 3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3855913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT 3865913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reckstatic inline MaybeObject* EnsureJSArrayWithWritableFastElements( 38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap, Object* receiver) { 388756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (!receiver->IsJSArray()) return NULL; 3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(receiver); 3909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HeapObject* elms = array->elements(); 39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (elms->map() == heap->fixed_array_map()) return elms; 39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (elms->map() == heap->fixed_cow_array_map()) { 393756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick return array->EnsureWritableFastElements(); 3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 395756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick return NULL; 3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 39944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, 40044f0eee88ff00398ff7f715fab053374d808c90dSteve Block JSArray* receiver) { 40144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Context* global_context = heap->isolate()->context()->global_context(); 40225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen JSObject* array_proto = 40325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen JSObject::cast(global_context->array_function()->prototype()); 404756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick return receiver->GetPrototype() == array_proto && 40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ArrayPrototypeHasNoElements(heap, global_context, array_proto); 40625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen} 40725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 40825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 4095913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT static MaybeObject* CallJsBuiltin( 41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate, 4115913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck const char* name, 4125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { 41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope handleScope(isolate); 4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> js_builtin = 41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block GetProperty(Handle<JSObject>( 41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->global_context()->builtins()), 41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block name); 4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(js_builtin->IsJSFunction()); 4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin)); 42125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ScopedVector<Object**> argv(args.length() - 1); 4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int n_args = args.length() - 1; 4236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < n_args; i++) { 4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argv[i] = args.at<Object>(i + 1).location(); 4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool pending_exception = false; 4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> result = Execution::Call(function, 4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block args.receiver(), 4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block n_args, 4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block argv.start(), 4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &pending_exception); 4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (pending_exception) return Failure::Exception(); 4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return *result; 4346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(ArrayPush) { 43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* receiver = *args.receiver(); 4405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* elms_obj; 4415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_elms_obj = 44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block EnsureJSArrayWithWritableFastElements(heap, receiver); 44344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (maybe_elms_obj == NULL) { 44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayPush", args); 44544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 4465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 4475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 448756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FixedArray* elms = FixedArray::cast(elms_obj); 4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(receiver); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int len = Smi::cast(array->length())->value(); 452402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int to_add = args.length() - 1; 453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (to_add == 0) { 454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return Smi::FromInt(len); 455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Currently fixed arrays cannot grow too big, so 457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // we should never hit this case. 458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(to_add <= (Smi::kMaxValue - len)); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int new_length = len + to_add; 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 462402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (new_length > elms->length()) { 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // New backing storage is needed. 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int capacity = new_length + (new_length >> 1) + 16; 4655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 4675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 4685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* new_elms = FixedArray::cast(obj); 4704515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 4714515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke AssertNoAllocation no_gc; 4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (len > 0) { 47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); 4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 47544f0eee88ff00398ff7f715fab053374d808c90dSteve Block FillWithHoles(heap, new_elms, new_length, capacity); 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 477402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu elms = new_elms; 478402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu array->set_elements(elms); 479402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Add the provided values. 482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AssertNoAllocation no_gc; 483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu for (int index = 0; index < to_add; index++) { 485402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu elms->set(index + len, args[index + 1], mode); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 487402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the length. 4894515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke array->set_length(Smi::FromInt(new_length)); 490402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return Smi::FromInt(new_length); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(ArrayPop) { 49544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* receiver = *args.receiver(); 4975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* elms_obj; 4985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_elms_obj = 49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block EnsureJSArrayWithWritableFastElements(heap, receiver); 50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (maybe_elms_obj == NULL) return CallJsBuiltin(isolate, "ArrayPop", args); 5015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 5025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 503756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FixedArray* elms = FixedArray::cast(elms_obj); 5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(receiver); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int len = Smi::cast(array->length())->value(); 50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (len == 0) return heap->undefined_value(); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get top element 5105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MaybeObject* top = elms->get(len - 1); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the length. 5134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke array->set_length(Smi::FromInt(len - 1)); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!top->IsTheHole()) { 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Delete the top element. 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block elms->set_the_hole(len - 1); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return top; 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen top = array->GetPrototype()->GetElement(len - 1); 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return top; 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuBUILTIN(ArrayShift) { 52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* receiver = *args.receiver(); 5305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* elms_obj; 5315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_elms_obj = 53244f0eee88ff00398ff7f715fab053374d808c90dSteve Block EnsureJSArrayWithWritableFastElements(heap, receiver); 53344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (maybe_elms_obj == NULL) 53444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayShift", args); 5355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 5365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 53744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 53844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayShift", args); 5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FixedArray* elms = FixedArray::cast(elms_obj); 5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(receiver); 542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(array->HasFastElements()); 543402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 544402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int len = Smi::cast(array->length())->value(); 54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (len == 0) return heap->undefined_value(); 546402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 547402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Get first element 548402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* first = elms->get(0); 549402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (first->IsTheHole()) { 55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block first = heap->undefined_value(); 551402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 552402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!heap->lo_space()->Contains(elms)) { 554791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block // As elms still in the same space they used to be, 5557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // there is no need to update region dirty mark. 55644f0eee88ff00398ff7f715fab053374d808c90dSteve Block array->set_elements(LeftTrimFixedArray(heap, elms, 1), SKIP_WRITE_BARRIER); 5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Shift the elements. 5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block MoveElements(heap, &no_gc, elms, 0, elms, 1, len - 1); 56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block elms->set(len - 1, heap->the_hole_value()); 562402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 563402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Set the length. 565402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu array->set_length(Smi::FromInt(len - 1)); 566402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 567402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return first; 568402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 569402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 570402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 571402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuBUILTIN(ArrayUnshift) { 57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* receiver = *args.receiver(); 5745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* elms_obj; 5755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_elms_obj = 57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block EnsureJSArrayWithWritableFastElements(heap, receiver); 57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (maybe_elms_obj == NULL) 57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayUnshift", args); 5795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 5805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 58144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 58244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayUnshift", args); 5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 584756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FixedArray* elms = FixedArray::cast(elms_obj); 5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(receiver); 586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(array->HasFastElements()); 587402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 588402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int len = Smi::cast(array->length())->value(); 589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int to_add = args.length() - 1; 590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int new_length = len + to_add; 591402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Currently fixed arrays cannot grow too big, so 592402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // we should never hit this case. 593402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(to_add <= (Smi::kMaxValue - len)); 594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (new_length > elms->length()) { 596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // New backing storage is needed. 597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int capacity = new_length + (new_length >> 1) + 16; 5985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 6005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 6015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* new_elms = FixedArray::cast(obj); 603402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 604402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AssertNoAllocation no_gc; 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (len > 0) { 60644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); 6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block FillWithHoles(heap, new_elms, new_length, capacity); 609402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 610402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu elms = new_elms; 611402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu array->set_elements(elms); 612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AssertNoAllocation no_gc; 61444f0eee88ff00398ff7f715fab053374d808c90dSteve Block MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); 615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 616402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 617402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Add the provided values. 618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AssertNoAllocation no_gc; 619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu for (int i = 0; i < to_add; i++) { 621402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu elms->set(i, args[i + 1], mode); 622402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 623402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 624402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Set the length. 625402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu array->set_length(Smi::FromInt(new_length)); 626402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return Smi::FromInt(new_length); 627402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 628402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 629402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuBUILTIN(ArraySlice) { 63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* receiver = *args.receiver(); 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FixedArray* elms; 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int len = -1; 6359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (receiver->IsJSArray()) { 6369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block JSArray* array = JSArray::cast(receiver); 6379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!array->HasFastElements() || 63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block !IsJSArrayFastElementMovingAllowed(heap, array)) { 63944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 6409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 6419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 6429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block elms = FixedArray::cast(array->elements()); 6439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block len = Smi::cast(array->length())->value(); 6449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 6459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Array.slice(arguments, ...) is quite a common idiom (notably more 6469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // than 50% of invocations in Web apps). Treat it in C++ as well. 6479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Map* arguments_map = 64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->context()->global_context()->arguments_boilerplate()->map(); 6499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 6509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block bool is_arguments_object_with_fast_elements = 6519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block receiver->IsJSObject() 6529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block && JSObject::cast(receiver)->map() == arguments_map 6539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block && JSObject::cast(receiver)->HasFastElements(); 6549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!is_arguments_object_with_fast_elements) { 65544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 6569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 6579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block elms = FixedArray::cast(JSObject::cast(receiver)->elements()); 658b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Object* len_obj = JSObject::cast(receiver) 65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 660b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!len_obj->IsSmi()) { 66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 662b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 663b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch len = Smi::cast(len_obj)->value(); 664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (len > elms->length()) { 66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 667b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < len; i++) { 66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (elms->get(i) == heap->the_hole_value()) { 66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(len >= 0); 674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int n_arguments = args.length() - 1; 675402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 676402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Note carefully choosen defaults---if argument is missing, 6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // it's undefined which gets converted to 0 for relative_start 6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and to len for relative_end. 6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int relative_start = 0; 6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int relative_end = len; 681402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (n_arguments > 0) { 682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* arg1 = args[1]; 683402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (arg1->IsSmi()) { 6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block relative_start = Smi::cast(arg1)->value(); 685402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else if (!arg1->IsUndefined()) { 68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 687402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 688402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (n_arguments > 1) { 689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* arg2 = args[2]; 690402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (arg2->IsSmi()) { 6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block relative_end = Smi::cast(arg2)->value(); 692402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else if (!arg2->IsUndefined()) { 69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySlice", args); 694402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 695402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 696402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 697402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. 6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int k = (relative_start < 0) ? Max(len + relative_start, 0) 7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : Min(relative_start, len); 701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 702402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int final = (relative_end < 0) ? Max(len + relative_end, 0) 7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : Min(relative_end, len); 705402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Calculate the length of result array. 707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int result_len = final - k; 7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result_len <= 0) { 70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return AllocateEmptyJSArray(heap); 710402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 711402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 7125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_result = AllocateJSArray(heap); 7145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 7155913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu JSArray* result_array = JSArray::cast(result); 717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 7185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_result = 71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->AllocateUninitializedFixedArray(result_len); 7205913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 7215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FixedArray* result_elms = FixedArray::cast(result); 723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu AssertNoAllocation no_gc; 72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len); 726402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 727402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Set elements. 728402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu result_array->set_elements(result_elms); 729402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 730402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Set the length. 731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu result_array->set_length(Smi::FromInt(result_len)); 732402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return result_array; 733402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 734402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 735402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuBUILTIN(ArraySplice) { 73744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 7386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* receiver = *args.receiver(); 7395913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* elms_obj; 7405913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_elms_obj = 74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block EnsureJSArrayWithWritableFastElements(heap, receiver); 74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (maybe_elms_obj == NULL) 74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySplice", args); 7445913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 7455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySplice", args); 7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 749756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick FixedArray* elms = FixedArray::cast(elms_obj); 7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(receiver); 751402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(array->HasFastElements()); 752402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 753402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int len = Smi::cast(array->length())->value(); 754402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 755402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int n_arguments = args.length() - 1; 756402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int relative_start = 0; 7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (n_arguments > 0) { 7591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Object* arg1 = args[1]; 7601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (arg1->IsSmi()) { 7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block relative_start = Smi::cast(arg1)->value(); 7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (!arg1->IsUndefined()) { 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySplice", args); 7641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 765402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : Min(relative_start, len); 768402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 769402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is 7701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // given as a request to delete all the elements from the start. 7711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // And it differs from the case of undefined delete count. 772402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // This does not follow ECMA-262, but we do the same for 773402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // compatibility. 7741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int actual_delete_count; 7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (n_arguments == 1) { 7761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(len - actual_start >= 0); 7771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block actual_delete_count = len - actual_start; 7781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 7791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int value = 0; // ToInteger(undefined) == 0 7801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (n_arguments > 1) { 7811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Object* arg2 = args[2]; 7821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (arg2->IsSmi()) { 7831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = Smi::cast(arg2)->value(); 7841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArraySplice", args); 7861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 787402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 7881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block actual_delete_count = Min(Max(value, 0), len - actual_start); 789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* result_array = NULL; 7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (actual_delete_count == 0) { 7935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_result = AllocateEmptyJSArray(heap); 7955913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 7965913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array = JSArray::cast(result); 7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Allocate result array. 8005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_result = AllocateJSArray(heap); 8025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 8035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array = JSArray::cast(result); 805402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_result = 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->AllocateUninitializedFixedArray(actual_delete_count); 8085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 8095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* result_elms = FixedArray::cast(result); 811402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill newly created array. 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block &no_gc, 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_elms, 0, 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms, actual_start, 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block actual_delete_count); 819402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set elements. 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array->set_elements(result_elms); 822402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the length. 8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array->set_length(Smi::FromInt(actual_delete_count)); 825402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 826402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 828402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int new_length = len - actual_delete_count + item_count; 830402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (item_count < actual_delete_count) { 832402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Shrink the array. 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block const bool trim_array = !heap->lo_space()->Contains(elms) && 8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ((actual_start + item_count) < 8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (len - actual_delete_count - actual_start)); 8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (trim_array) { 8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int delta = actual_delete_count - item_count; 8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (actual_start > 0) { 840053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block AssertNoAllocation no_gc; 841053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block MoveElements(heap, &no_gc, elms, delta, elms, 0, actual_start); 8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 843402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block elms = LeftTrimFixedArray(heap, elms, delta); 8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block array->set_elements(elms, SKIP_WRITE_BARRIER); 8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block MoveElements(heap, &no_gc, 8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms, actual_start + item_count, 8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms, actual_start + actual_delete_count, 8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (len - actual_delete_count - actual_start)); 85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FillWithHoles(heap, elms, new_length, len); 853402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (item_count > actual_delete_count) { 855402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Currently fixed arrays cannot grow too big, so 856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // we should never hit this case. 8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len)); 858402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Check if array need to grow. 860402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (new_length > elms->length()) { 861402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // New backing storage is needed. 862402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu int capacity = new_length + (new_length >> 1) + 16; 8635913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* obj; 8645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_obj = 86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->AllocateUninitializedFixedArray(capacity); 8665913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8675913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 868402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FixedArray* new_elms = FixedArray::cast(obj); 869402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Copy the part before actual_start as is. 8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (actual_start > 0) { 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start); 874402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int to_copy = len - actual_delete_count - actual_start; 8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (to_copy > 0) { 87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, &no_gc, 8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block new_elms, actual_start + item_count, 8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms, actual_start + actual_delete_count, 8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block to_copy); 8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FillWithHoles(heap, new_elms, new_length, capacity); 883402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu elms = new_elms; 885402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu array->set_elements(elms); 8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block MoveElements(heap, &no_gc, 8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms, actual_start + item_count, 8906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms, actual_start + actual_delete_count, 8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (len - actual_delete_count - actual_start)); 892402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 893402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 894402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int k = actual_start; k < actual_start + item_count; k++) { 8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block elms->set(k, args[3 + k - actual_start], mode); 899402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 900402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 901402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Set the length. 902402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu array->set_length(Smi::FromInt(new_length)); 903402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 904402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return result_array; 905402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 906402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 9086ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockBUILTIN(ArrayConcat) { 90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 91044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Context* global_context = isolate->context()->global_context(); 91125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen JSObject* array_proto = 91225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen JSObject::cast(global_context->array_function()->prototype()); 91344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { 91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayConcat", args); 9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Iterate through all the arguments performing checks 9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // and calculating total length. 9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int n_arguments = args.length(); 9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_len = 0; 9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < n_arguments; i++) { 9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* arg = args[i]; 92325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() 92425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen || JSArray::cast(arg)->GetPrototype() != array_proto) { 92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayConcat", args); 9266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len = Smi::cast(JSArray::cast(arg)->length())->value(); 9296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We shouldn't overflow when adding another len. 9316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block USE(kHalfOfMaxInt); 9346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_len += len; 9356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(result_len >= 0); 9366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result_len > FixedArray::kMaxLength) { 93844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return CallJsBuiltin(isolate, "ArrayConcat", args); 9396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result_len == 0) { 94344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return AllocateEmptyJSArray(heap); 9446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Allocate result. 9475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* result; 94844f0eee88ff00398ff7f715fab053374d808c90dSteve Block { MaybeObject* maybe_result = AllocateJSArray(heap); 9495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 9505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* result_array = JSArray::cast(result); 9526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_result = 95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->AllocateUninitializedFixedArray(result_len); 9555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_result->ToObject(&result)) return maybe_result; 9565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* result_elms = FixedArray::cast(result); 9586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Copy data. 9606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_gc; 9616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int start_pos = 0; 9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < n_arguments; i++) { 9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(args[i]); 9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len = Smi::cast(array->length())->value(); 9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (len > 0) { 9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixedArray* elms = FixedArray::cast(array->elements()); 96744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); 9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block start_pos += len; 9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(start_pos == result_len); 9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set the length and elements. 9746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array->set_length(Smi::FromInt(result_len)); 9756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_array->set_elements(result_elms); 9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result_array; 9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------- 98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Strict mode poison pills 98344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 98544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN(StrictArgumentsCallee) { 98644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope; 98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->Throw(*isolate->factory()->NewTypeError( 98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block "strict_arguments_callee", HandleVector<Object>(NULL, 0))); 98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 99044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 99244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN(StrictArgumentsCaller) { 99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope; 99444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->Throw(*isolate->factory()->NewTypeError( 99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block "strict_arguments_caller", HandleVector<Object>(NULL, 0))); 99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 99744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 99944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN(StrictFunctionCaller) { 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope; 100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->Throw(*isolate->factory()->NewTypeError( 100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block "strict_function_caller", HandleVector<Object>(NULL, 0))); 100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 100644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN(StrictFunctionArguments) { 100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope; 100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->Throw(*isolate->factory()->NewTypeError( 100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block "strict_function_arguments", HandleVector<Object>(NULL, 0))); 101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 101344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// ----------------------------------------------------------------------------- 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the holder JSObject if the function can legally be called 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with this receiver. Returns Heap::null_value() if the call is 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// illegal. Any arguments that don't fit the expected type is 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// overwritten with undefined. Arguments that do fit the expected 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// type is overwritten with the object in the prototype chain that 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// actually has that type. 102344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic inline Object* TypeCheck(Heap* heap, 102444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int argc, 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** argv, 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FunctionTemplateInfo* info) { 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* recv = argv[0]; 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* sig_obj = info->signature(); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (sig_obj->IsUndefined()) return recv; 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SignatureInfo* sig = SignatureInfo::cast(sig_obj); 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If necessary, check the receiver 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* recv_type = sig->receiver(); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* holder = recv; 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!recv_type->IsUndefined()) { 103644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (; holder != heap->null_value(); holder = holder->GetPrototype()) { 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) { 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (holder == heap->null_value()) return holder; 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* args_obj = sig->args(); 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is no argument signature we're done 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (args_obj->IsUndefined()) return holder; 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixedArray* args = FixedArray::cast(args_obj); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int length = args->length(); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (argc <= length) length = argc - 1; 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < length; i++) { 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* argtype = args->get(i); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (argtype->IsUndefined()) continue; 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** arg = &argv[-1 - i]; 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* current = *arg; 105444f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (; current != heap->null_value(); current = current->GetPrototype()) { 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) { 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *arg = current; 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current == heap->null_value()) *arg = heap->undefined_value(); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return holder; 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1066e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketemplate <bool is_construct> 10675913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT static MaybeObject* HandleApiCallHelper( 106844f0eee88ff00398ff7f715fab053374d808c90dSteve Block BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) { 106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(is_construct == CalledAsConstructor(isolate)); 107044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate); 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Handle<JSFunction> function = args.called_function(); 10746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(function->shared()->IsApiFunction()); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data(); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_construct) { 107844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<FunctionTemplateInfo> desc(fun_data, isolate); 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool pending_exception = false; 108044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->factory()->ConfigureInstance( 108144f0eee88ff00398ff7f715fab053374d808c90dSteve Block desc, Handle<JSObject>::cast(args.receiver()), &pending_exception); 108244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate->has_pending_exception() == pending_exception); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pending_exception) return Failure::Exception(); 10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block fun_data = *desc; 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Object* raw_holder = TypeCheck(heap, args.length(), &args[0], fun_data); 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (raw_holder->IsNull()) { 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This function cannot be called with the given receiver. Abort! 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> obj = 109244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->factory()->NewTypeError( 109344f0eee88ff00398ff7f715fab053374d808c90dSteve Block "illegal_invocation", HandleVector(&function, 1)); 109444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return isolate->Throw(*obj); 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* raw_call_data = fun_data->call_code(); 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!raw_call_data->IsUndefined()) { 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* callback_obj = call_data->callback(); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::InvocationCallback callback = 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::ToCData<v8::InvocationCallback>(callback_obj); 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* data_obj = call_data->data(); 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result; 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); 11073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(raw_holder->IsJSObject()); 11083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 110944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CustomArguments custom(isolate); 11103e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu v8::ImplementationUtilities::PrepareArgumentsData(custom.end(), 11113e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu data_obj, *function, raw_holder); 11123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( 11143e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu custom.end(), 11153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &args[0] - 1, 11163e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu args.length() - 1, 11173e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu is_construct); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Value> value; 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leaving JavaScript. 112244f0eee88ff00398ff7f715fab053374d808c90dSteve Block VMState state(isolate, EXTERNAL); 112344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalCallbackScope call_scope(isolate, 112444f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::ToCData<Address>(callback_obj)); 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = callback(new_args); 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value.IsEmpty()) { 112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block result = heap->undefined_value(); 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = *reinterpret_cast<Object**>(*value); 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!is_construct || result->IsJSObject()) return result; 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return *args.receiver(); 1138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1140e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeBUILTIN(HandleApiCall) { 114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return HandleApiCallHelper<false>(args, isolate); 1143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1144e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1145e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1146e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeBUILTIN(HandleApiCallConstruct) { 114744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return HandleApiCallHelper<true>(args, isolate); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1151402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#ifdef DEBUG 1152402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1153402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void VerifyTypeCheck(Handle<JSObject> object, 1154402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Handle<JSFunction> function) { 11556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(function->shared()->IsApiFunction()); 11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FunctionTemplateInfo* info = function->shared()->get_api_func_data(); 1157402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (info->signature()->IsUndefined()) return; 1158402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SignatureInfo* signature = SignatureInfo::cast(info->signature()); 1159402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* receiver_type = signature->receiver(); 1160402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (receiver_type->IsUndefined()) return; 1161402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type); 1162402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(object->IsInstanceOf(type)); 1163402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1164402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1165402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#endif 1166402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1167402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1168402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuBUILTIN(FastHandleApiCall) { 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!CalledAsConstructor(isolate)); 117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 1171402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const bool is_construct = false; 1172402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 11738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // We expect four more arguments: callback, function, call data, and holder. 1174402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu const int args_length = args.length() - 4; 1175402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu ASSERT(args_length >= 0); 1176402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 11778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Object* callback_obj = args[args_length]; 1178402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1179402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( 11808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang &args[args_length + 1], 11813e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &args[0] - 1, 11823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu args_length - 1, 11833e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu is_construct); 1184402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 11858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef DEBUG 11868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()), 11878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Utils::OpenHandle(*new_args.Callee())); 11888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif 118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate); 1190402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Object* result; 1191402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu v8::Handle<v8::Value> value; 1192402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu { 1193402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Leaving JavaScript. 119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block VMState state(isolate, EXTERNAL); 119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalCallbackScope call_scope(isolate, 119644f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::ToCData<Address>(callback_obj)); 11973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu v8::InvocationCallback callback = 11983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu v8::ToCData<v8::InvocationCallback>(callback_obj); 11993e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1200402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu value = callback(new_args); 1201402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1202402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (value.IsEmpty()) { 120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block result = heap->undefined_value(); 1204402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 1205402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu result = *reinterpret_cast<Object**>(*value); 1206402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1207402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1209402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return result; 1210402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1211402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1212402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function to handle calls to non-function objects created through the 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// API. The object can be called as either a constructor (using new) or just as 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a function (without new). 12165913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor( 121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate, 1218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke bool is_construct_call, 1219e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Non-functions are never called as constructors. Even if this is an object 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // called as a constructor the delegate call is not a construct call. 122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!CalledAsConstructor(isolate)); 122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap* heap = isolate->heap(); 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> receiver = args.at<Object>(0); 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the object called. 1228e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke JSObject* obj = JSObject::cast(*args.receiver()); 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the invocation callback from the function descriptor that was 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // used to create the called object. 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(obj->map()->has_instance_call_handler()); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); 12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(constructor->shared()->IsApiFunction()); 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* handler = 12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block constructor->shared()->get_api_func_data()->instance_call_handler(); 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!handler->IsUndefined()); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* callback_obj = call_data->callback(); 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::InvocationCallback callback = 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::ToCData<v8::InvocationCallback>(callback_obj); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the data for the call and perform the callback. 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result; 12453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu { 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate); 124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(isolate, ApiObjectAccess("call non-function", obj)); 12483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CustomArguments custom(isolate); 12503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu v8::ImplementationUtilities::PrepareArgumentsData(custom.end(), 12513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu call_data->data(), constructor, obj); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( 12533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu custom.end(), 12543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu &args[0] - 1, 12553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu args.length() - 1, 12563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu is_construct_call); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Value> value; 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leaving JavaScript. 126044f0eee88ff00398ff7f715fab053374d808c90dSteve Block VMState state(isolate, EXTERNAL); 126144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalCallbackScope call_scope(isolate, 126244f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::ToCData<Address>(callback_obj)); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value = callback(new_args); 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value.IsEmpty()) { 126644f0eee88ff00398ff7f715fab053374d808c90dSteve Block result = heap->undefined_value(); 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = *reinterpret_cast<Object**>(*value); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for exceptions and return result. 127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle calls to non-function objects created through the API. This delegate 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function is used when the call is a normal function call. 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(HandleApiCallAsFunction) { 128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return HandleApiCallAsFunctionOrConstructor(isolate, false, args); 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Handle calls to non-function objects created through the API. This delegate 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function is used when the call is a construct call. 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBUILTIN(HandleApiCallAsConstructor) { 128744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return HandleApiCallAsFunctionOrConstructor(isolate, true, args); 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_ArrayLength(MacroAssembler* masm) { 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GenerateArrayLength(masm); 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_StringLength(MacroAssembler* masm) { 12971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LoadIC::GenerateStringLength(masm, false); 12981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 12991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_LoadIC_StringWrapperLength(MacroAssembler* masm) { 13021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LoadIC::GenerateStringLength(masm, true); 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) { 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GenerateFunctionPrototype(masm); 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_Initialize(MacroAssembler* masm) { 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GenerateInitialize(masm); 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) { 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GeneratePreMonomorphic(masm); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_Miss(MacroAssembler* masm) { 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GenerateMiss(masm); 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_Megamorphic(MacroAssembler* masm) { 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GenerateMegamorphic(masm); 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_Normal(MacroAssembler* masm) { 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadIC::GenerateNormal(masm); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) { 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block KeyedLoadIC::GenerateInitialize(masm); 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) { 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block KeyedLoadIC::GenerateMiss(masm); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) { 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block KeyedLoadIC::GenerateGeneric(masm); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1351e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic void Generate_KeyedLoadIC_String(MacroAssembler* masm) { 1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke KeyedLoadIC::GenerateString(masm); 1353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) { 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block KeyedLoadIC::GeneratePreMonomorphic(masm); 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1360402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) { 1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu KeyedLoadIC::GenerateIndexedInterceptor(masm); 1362402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1363402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_StoreIC_Initialize(MacroAssembler* masm) { 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StoreIC::GenerateInitialize(masm); 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_Initialize_Strict(MacroAssembler* masm) { 13711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StoreIC::GenerateInitialize(masm); 13721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 13731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_StoreIC_Miss(MacroAssembler* masm) { 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StoreIC::GenerateMiss(masm); 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13808defd9ff6930b4e24729971a61cf7469daf119beSteve Blockstatic void Generate_StoreIC_Normal(MacroAssembler* masm) { 13818defd9ff6930b4e24729971a61cf7469daf119beSteve Block StoreIC::GenerateNormal(masm); 13828defd9ff6930b4e24729971a61cf7469daf119beSteve Block} 13838defd9ff6930b4e24729971a61cf7469daf119beSteve Block 13848defd9ff6930b4e24729971a61cf7469daf119beSteve Block 13851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_Normal_Strict(MacroAssembler* masm) { 13861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StoreIC::GenerateNormal(masm); 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_Megamorphic(MacroAssembler* masm) { 1391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StoreIC::GenerateMegamorphic(masm, kNonStrictMode); 13923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) { 1396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StoreIC::GenerateMegamorphic(masm, kStrictMode); 13973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_ArrayLength(MacroAssembler* masm) { 14011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StoreIC::GenerateArrayLength(masm); 14023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_ArrayLength_Strict(MacroAssembler* masm) { 14061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StoreIC::GenerateArrayLength(masm); 14073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_GlobalProxy(MacroAssembler* masm) { 1411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StoreIC::GenerateGlobalProxy(masm, kNonStrictMode); 14123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_StoreIC_GlobalProxy_Strict(MacroAssembler* masm) { 1416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch StoreIC::GenerateGlobalProxy(masm, kStrictMode); 14173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) { 1421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode); 1422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) { 1426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch KeyedStoreIC::GenerateGeneric(masm, kStrictMode); 14273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 14283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 14293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) { 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block KeyedStoreIC::GenerateMiss(masm); 1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) { 1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block KeyedStoreIC::GenerateInitialize(masm); 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) { 1441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch KeyedStoreIC::GenerateInitialize(masm); 1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_LoadIC_DebugBreak(MacroAssembler* masm) { 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateLoadICDebugBreak(masm); 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_StoreIC_DebugBreak(MacroAssembler* masm) { 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateStoreICDebugBreak(masm); 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) { 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateKeyedLoadICDebugBreak(masm); 1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) { 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateKeyedStoreICDebugBreak(masm); 1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) { 1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateConstructCallDebugBreak(masm); 1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_Return_DebugBreak(MacroAssembler* masm) { 1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateReturnDebugBreak(masm); 1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) { 1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::GenerateStubNoRegistersDebugBreak(masm); 1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochstatic void Generate_Slot_DebugBreak(MacroAssembler* masm) { 14827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Debug::GenerateSlotDebugBreak(masm); 14837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 14847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) { 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Debug::GeneratePlainReturnLiveEdit(masm); 14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) { 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Debug::GenerateFrameDropperLiveEdit(masm); 14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 149744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBuiltins::Builtins() : initialized_(false) { 149844f0eee88ff00398ff7f715fab053374d808c90dSteve Block memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count); 149944f0eee88ff00398ff7f715fab053374d808c90dSteve Block memset(names_, 0, sizeof(names_[0]) * builtin_count); 150044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 150144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 150244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 150344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBuiltins::~Builtins() { 150444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 150544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name), 150844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockAddress const Builtins::c_functions_[cfunction_count] = { 150944f0eee88ff00398ff7f715fab053374d808c90dSteve Block BUILTIN_LIST_C(DEF_ENUM_C) 151044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_ENUM_C 1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DEF_JS_NAME(name, ignore) #name, 1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DEF_JS_ARGC(ignore, argc) argc, 151544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst char* const Builtins::javascript_names_[id_count] = { 1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BUILTINS_LIST_JS(DEF_JS_NAME) 1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint const Builtins::javascript_argc_[id_count] = { 1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BUILTINS_LIST_JS(DEF_JS_ARGC) 1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_JS_NAME 1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_JS_ARGC 1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstruct BuiltinDesc { 152644f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte* generator; 152744f0eee88ff00398ff7f715fab053374d808c90dSteve Block byte* c_code; 152844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* s_name; // name is only used for generating log information. 152944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int name; 153044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Code::Flags flags; 153144f0eee88ff00398ff7f715fab053374d808c90dSteve Block BuiltinExtraArguments extra_args; 153244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass BuiltinFunctionTable { 153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 153644f0eee88ff00398ff7f715fab053374d808c90dSteve Block BuiltinFunctionTable() { 153744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Builtins::InitBuiltinFunctionTable(); 153844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 153944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 154044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const BuiltinDesc* functions() { return functions_; } 154144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 154244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 154344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static BuiltinDesc functions_[Builtins::builtin_count + 1]; 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154544f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class Builtins; 154644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 154844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBuiltinDesc BuiltinFunctionTable::functions_[Builtins::builtin_count + 1]; 154944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 155044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const BuiltinFunctionTable builtin_function_table_init; 155144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 155244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Define array of pointers to generators and C builtin functions. 155344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// We do this in a sort of roundabout way so that we can do the initialization 155444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// within the lexical scope of Builtins:: and within a context where 155544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Code::Flags names a non-abstract type. 155644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::InitBuiltinFunctionTable() { 155744f0eee88ff00398ff7f715fab053374d808c90dSteve Block BuiltinDesc* functions = BuiltinFunctionTable::functions_; 155844f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions[builtin_count].generator = NULL; 155944f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions[builtin_count].c_code = NULL; 156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions[builtin_count].s_name = NULL; 156144f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions[builtin_count].name = builtin_count; 156244f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions[builtin_count].flags = static_cast<Code::Flags>(0); 156344f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS; 156444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 156544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEF_FUNCTION_PTR_C(aname, aextra_args) \ 156644f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->generator = FUNCTION_ADDR(Generate_Adaptor); \ 156744f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->c_code = FUNCTION_ADDR(Builtin_##aname); \ 156844f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->s_name = #aname; \ 156944f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->name = c_##aname; \ 157044f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->flags = Code::ComputeFlags(Code::BUILTIN); \ 157144f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->extra_args = aextra_args; \ 157244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ++functions; 157344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 157444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \ 157544f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->generator = FUNCTION_ADDR(Generate_##aname); \ 157644f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->c_code = NULL; \ 157744f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->s_name = #aname; \ 157844f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->name = k##aname; \ 157944f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->flags = Code::ComputeFlags(Code::kind, \ 158044f0eee88ff00398ff7f715fab053374d808c90dSteve Block NOT_IN_LOOP, \ 158144f0eee88ff00398ff7f715fab053374d808c90dSteve Block state, \ 158244f0eee88ff00398ff7f715fab053374d808c90dSteve Block extra); \ 158344f0eee88ff00398ff7f715fab053374d808c90dSteve Block functions->extra_args = NO_EXTRA_ARGUMENTS; \ 158444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ++functions; 158544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 158644f0eee88ff00398ff7f715fab053374d808c90dSteve Block BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) 158744f0eee88ff00398ff7f715fab053374d808c90dSteve Block BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) 158844f0eee88ff00398ff7f715fab053374d808c90dSteve Block BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A) 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_FUNCTION_PTR_C 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_FUNCTION_PTR_A 159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 159444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Builtins::Setup(bool create_heap_objects) { 159544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!initialized_); 15968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Isolate* isolate = Isolate::Current(); 15978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Heap* heap = isolate->heap(); 159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Create a scope for the handles in the builtins. 16008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HandleScope scope(isolate); 160144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 160244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const BuiltinDesc* functions = BuiltinFunctionTable::functions(); 1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // For now we generate builtin adaptor code into a stack-allocated 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // buffer, before copying it into individual code objects. 1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte buffer[4*KB]; 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Traverse the list of builtins and generate an adaptor in a 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // separate code object for each one. 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < builtin_count; i++) { 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (create_heap_objects) { 16128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler masm(isolate, buffer, sizeof buffer); 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Generate the code/adaptor. 1614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments); 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generator g = FUNCTION_CAST<Generator>(functions[i].generator); 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We pass all arguments to the generator, but it may not use all of 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // them. This works because the first arguments are on top of the 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // stack. 1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke g(&masm, functions[i].name, functions[i].extra_args); 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move the code into the object heap. 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc desc; 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm.GetCode(&desc); 1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags = functions[i].flags; 1624b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Object* code = NULL; 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // During startup it's OK to always allocate and defer GC to later. 1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This simplifies things because we don't need to retry. 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AlwaysAllocateScope __scope__; 16295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck { MaybeObject* maybe_code = 163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block heap->CreateCode(desc, flags, masm.CodeObject()); 16315913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck if (!maybe_code->ToObject(&code)) { 16325913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); 16335913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Log the event and add the code to the builtins array. 16378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PROFILE(isolate, 163844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CodeCreateEvent(Logger::BUILTIN_TAG, 1639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Code::cast(code), 1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch functions[i].s_name)); 1641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GDBJIT(AddCode(GDBJITInterface::BUILTIN, 1642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch functions[i].s_name, 1643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Code::cast(code))); 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builtins_[i] = code; 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DISASSEMBLER 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_print_builtin_code) { 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("Builtin: %s\n", functions[i].s_name); 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::cast(code)->Disassemble(functions[i].s_name); 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("\n"); 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Deserializing. The values will be filled in during IterateBuiltins. 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block builtins_[i] = NULL; 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block names_[i] = functions[i].s_name; 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mark as initialized. 166044f0eee88ff00398ff7f715fab053374d808c90dSteve Block initialized_ = true; 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::TearDown() { 166544f0eee88ff00398ff7f715fab053374d808c90dSteve Block initialized_ = false; 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::IterateBuiltins(ObjectVisitor* v) { 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count); 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* Builtins::Lookup(byte* pc) { 167544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // may be called during initialization (disassembler!) 167644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (initialized_) { 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < builtin_count; i++) { 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* entry = Code::cast(builtins_[i]); 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (entry->contains(pc)) { 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return names_[i]; 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 168844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \ 168944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandle<Code> Builtins::name() { \ 169044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Code** code_address = \ 169144f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<Code**>(builtin_address(k##name)); \ 169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Handle<Code>(code_address); \ 169344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 169444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \ 169544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandle<Code> Builtins::name() { \ 169644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Code** code_address = \ 169744f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<Code**>(builtin_address(k##name)); \ 169844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return Handle<Code>(code_address); \ 169944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 170044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 170144f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 170244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockBUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 170344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef DEFINE_BUILTIN_ACCESSOR_C 170444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#undef DEFINE_BUILTIN_ACCESSOR_A 170544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 170644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 1708