13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/assembler-inl.h" 8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/ast/compile-time-value.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ast/scopes.h" 1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-constructor.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 14f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compilation-info.h" 15f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler.h" 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/full-codegen/full-codegen.h" 1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/heap/heap-inl.h" 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 25109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define __ ACCESS_MASM(masm()) 261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED { 281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 29589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block info_emitted_ = false; 321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ~JumpPatchSite() { 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(patch_site_.is_bound() == info_emitted_); 371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJumpIfNotSmi(Register reg, 40257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* target, 41257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar) { 421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(reg, Immediate(kSmiTagMask)); 43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitJump(not_carry, target, near_jump); // Always taken before patched. 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJumpIfSmi(Register reg, 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* target, 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar) { 491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(reg, Immediate(kSmiTagMask)); 50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitJump(carry, target, near_jump); // Never taken before patched. 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitPatchInfo() { 543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (patch_site_.is_bound()) { 553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_uint8(delta_to_patch_site)); 573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testl(rax, Immediate(delta_to_patch_site)); 581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info_emitted_ = true; 601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Signals no inlined code. 633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // jc will be patched with jz, jnc will become jnz. 68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!patch_site_.is_bound() && !info_emitted_); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cc == carry || cc == not_carry); 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(cc, target, near_jump); 731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 75109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm() { return masm_; } 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MacroAssembler* masm_; 771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label patch_site_; 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool info_emitted_; 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// o rdi: the JS function object being called (i.e. ourselves) 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o rdx: the new target value 923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsi: our context 933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rbp: our caller's frame pointer 943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsp: stack pointer (pointing to return address) 953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout. 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() { 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompilationInfo* info = info_; 100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(scope(), info->scope()); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiling_counter_ = isolate()->factory()->NewCell( 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetFunctionPosition(literal()); 1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 1053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) { 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetReceiverOperand()); 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(rcx); 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rcx); 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver); 114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done below). 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->set_prologue_offset(masm_->pc_offset()); 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Prologue(info->GeneratePreagedPrologue()); 123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment invocation count for the function. 125f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 126f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Comment cmnt(masm_, "[ Increment invocation count"); 12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kFeedbackVectorOffset)); 12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ movp(rcx, FieldOperand(rcx, Cell::kValueOffset)); 129f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ SmiAddConstant( 13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FieldOperand(rcx, FeedbackVector::kInvocationCountIndex * kPointerSize + 13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackVector::kHeaderSize), 132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Smi::FromInt(1)); 133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int locals_count = info->scope()->num_stack_slots(); 137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(locals_count); 138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count == 1) { 139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ PushRoot(Heap::kUndefinedValueRootIndex); 140756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (locals_count > 1) { 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= 128) { 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rsp); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rcx, Immediate(locals_count * kPointerSize)); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, &ok, Label::kNear); 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kMaxPushes = 32; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= kMaxPushes) { 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int loop_iterations = locals_count / kMaxPushes; 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Immediate(loop_iterations)); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop_header; 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop_header); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do pushes. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kMaxPushes; i++) { 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(rax); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Continue loop if not done. 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ decp(rcx); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop_header, Label::kNear); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int remaining = locals_count % kMaxPushes; 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the remaining pushes. 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < remaining; i++) { 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(rax); 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 171756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 1744515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 175756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (info->scope()->NeedsContext()) { 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate context"); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is still in rdi. 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->is_script_scope()) { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 183f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(info->scope()->scope_info()); 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNewScriptContext); 185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::ScriptContext(), 186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The new target value is not used, clobbering is safe. 188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_NULL(info->scope()->new_target_var()); 189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->new_target_var() != nullptr) { 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(rdx); // Preserve new target. 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (slots <= 19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) { 19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::FastNewFunctionContext( 19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), info->scope()->scope_type()); 197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Set(FastNewFunctionContextDescriptor::SlotsRegister(), slots); 19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Result of the FastNewFunctionContext builtin is always in new space. 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch need_write_barrier = false; 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(rdi); 20362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(Smi::FromInt(info->scope()->scope_type())); 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (info->scope()->new_target_var() != nullptr) { 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(rdx); // Restore new target. 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in rax. It replaces the context passed to us. 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in rsi. 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, rax); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); 215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int first_parameter = info->scope()->has_this_declaration() ? -1 : 0; 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = first_parameter; i < num_parameters; i++) { 220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* var = 221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i); 222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 223756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 224756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 225756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rbp, parameter_offset)); 227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_offset = Context::SlotOffset(var->index()); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsi, context_offset), rax); 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. This clobbers rax and rbx. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rsi, context_offset, rax, rbx, kDontSaveFPRegs); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 2433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Register holding this function and new target are both trashed in case we 245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // bailout here. But since that can happen only when new target is not used 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // and we allocate a context, the value of |function_in_register| is correct. 247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::FunctionContext(), 248bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 25062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We don't support new.target and rest parameters here. 25162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NULL(info->scope()->new_target_var()); 25262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NULL(info->scope()->rest_parameter()); 25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_NULL(info->scope()->this_function_var()); 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate an arguments object. 256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(scope(), info->scope()); 257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Variable* arguments = info->scope()->arguments(); 258756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 259756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments object must be allocated after the context object, in 260756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // case the "arguments" or ".arguments" variables are in the context. 261756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!function_in_register) { 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (is_strict(language_mode()) || !has_simple_parameters()) { 26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ call(isolate()->builtins()->FastNewStrictArguments(), 26762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 26862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RestoreContext(); 269109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else if (literal()->has_duplicate_parameters()) { 270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(rdi); 271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kNewSloppyArguments_Generic); 272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ call(isolate()->builtins()->FastNewSloppyArguments(), 27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RestoreContext(); 276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 27744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SetVar(arguments, rax, rbx, rdx); 279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kTraceEnter); 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Visit the declarations and body unless there is an illegal 286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // redeclaration. 287bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::FunctionEntry(), 288bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 2893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment cmnt(masm_, "[ Declarations"); 291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch VisitDeclarations(info->scope()->declarations()); 2923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 293589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Assert that the declarations do not use ICs. Otherwise the debugger 2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // won't be able to redirect a PC at an IC to the correct IC in newly 2963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // recompiled code. 2973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ(0, ic_total_count_); 2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Comment cmnt(masm_, "[ Stack check"); 301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(BailoutId::Declarations(), 302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label ok; 3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(above_equal, &ok, Label::kNear); 3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); 3073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ bind(&ok); 3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch } 309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch { 3113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Comment cmnt(masm_, "[ Body"); 3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(loop_depth() == 0); 3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch VisitStatements(literal()->body()); 3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(loop_depth() == 0); 3153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body. 3193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 3203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 3217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 326db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() { 3279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Set(rax, 0); 328db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch} 329db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 330db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset), 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(-delta)); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int reset_value = FLAG_interrupt_budget; 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, Smi::FromInt(reset_value)); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister); 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14; 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* back_edge_target) { 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Back edge bookkeeping"); 352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(back_edge_target->is_bound()); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = Min(kMaxBackEdgeWeight, 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(positive, &ok, Label::kNear); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the AST id from the unoptimized code in order to use it as a key into 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the deoptimization input data found in the optimized code. 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordBackEdge(stmt->OsrEntryId()); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&ok); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS); 376086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 377086aeeaae12517475c22695a200be45495516549Ben Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 378086aeeaae12517475c22695a200be45495516549Ben Murdoch // we want it to work if it is. 379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS); 380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 382109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence( 383109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch bool is_tail_call) { 384109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Pretend that the exit is a backwards jump to the entry. 385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int weight = 1; 386109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (info_->ShouldSelfOptimize()) { 387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } else { 389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int distance = masm_->pc_offset(); 390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier)); 391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterDecrement(weight); 393109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label ok; 394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(positive, &ok, Label::kNear); 395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Don't need to save result register if we are going to do a tail call. 396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!is_tail_call) { 397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(rax); 398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!is_tail_call) { 401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(rax); 402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 403109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterReset(); 404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&ok); 405109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 411d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 412d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kTraceExit); 4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 417109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterHandlingForReturnSequence(false); 4181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetReturnPosition(literal()); 420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ leave(); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int arg_count = info_->scope()->num_parameters() + 1; 423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int arguments_bytes = arg_count * kPointerSize; 424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Ret(arguments_bytes, rcx); 4253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid FullCodeGenerator::RestoreContext() { 429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 4313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand operand = codegen()->VarOperand(var, result_register()); 435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->PushOperand(operand); 436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4390d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 451109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->OperandStackDepthIncrement(1); 4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(index); 4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 4630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 470e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (lit->IsSmi()) { 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SafeMove(result_register(), Smi::cast(*lit)); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result_register(), lit); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 486e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 489109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->OperandStackDepthIncrement(1); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (lit->IsSmi()) { 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SafePush(Smi::cast(*lit)); 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(lit); 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 50362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(lit->IsNullOrUndefined(isolate()) || !lit->IsUndetectable()); 50462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (lit->IsNullOrUndefined(isolate()) || lit->IsFalse(isolate())) { 505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 50613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) { 507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), lit); 5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (count > 1) codegen()->DropOperands(count - 1); 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 0), reg); 533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == materialize_false); 5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(result_register(), isolate()->factory()->true_value()); 549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(result_register(), isolate()->factory()->false_value()); 5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->OperandStackDepthIncrement(1); 560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(isolate()->factory()->true_value()); 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(isolate()->factory()->false_value()); 5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == true_label_); 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_false == false_label_); 5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 585109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch codegen()->OperandStackDepthIncrement(1); 5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(value_root_index); 5890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 594086aeeaae12517475c22695a200be45495516549Ben Murdoch true, 595086aeeaae12517475c22695a200be45495516549Ben Murdoch true_label_, 596086aeeaae12517475c22695a200be45495516549Ben Murdoch false_label_); 5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ jmp(true_label_); 5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 6000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ jmp(false_label_); 601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 602f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 6063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* if_true, 60780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 60880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 6093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate()); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, condition->test_id()); 611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); 612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(equal, if_true, if_false, fall_through); 61380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 61680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc, 61780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 61880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 61980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 62080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 62180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 62280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 62380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(NegateCondition(cc), if_false); 62480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 62580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 62680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated()); 633589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Offset is negative because higher indexes are at lower addresses. 634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = -var->index() * kPointerSize; 635589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Adjust by a (parameter or local) base offset. 636589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsParameter()) { 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset += kFPOnStackSize + kPCOnStackSize + 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (info_->scope()->num_parameters() - 1) * kPointerSize; 639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 642589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Operand(rbp, offset); 643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 646589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 648589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 649589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 650589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ LoadContext(scratch, context_chain_length); 651589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(scratch, var->index()); 652589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 653589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return StackOperand(var); 654589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 658589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 660589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, dest); 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(dest, location); 662589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 663589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 664589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var, 666589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register src, 667589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch0, 668589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1) { 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(src)); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(scratch1)); 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(src)); 673589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, scratch0); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(location, src); 6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 677589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 678589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = Context::SlotOffset(var->index()); 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool should_normalize, 686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_true, 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_false) { 688086aeeaae12517475c22695a200be45495516549Ben Murdoch // Only prepare for bailouts before splits if we're in a test 689086aeeaae12517475c22695a200be45495516549Ben Murdoch // context. Otherwise, we let the Visit function deal with the 690086aeeaae12517475c22695a200be45495516549Ben Murdoch // preparation to avoid preparing with the same AST id twice. 691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!context()->IsTest()) return; 692086aeeaae12517475c22695a200be45495516549Ben Murdoch 693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (should_normalize) __ jmp(&skip, Label::kNear); 695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr, BailoutState::TOS_REGISTER); 696086aeeaae12517475c22695a200be45495516549Ben Murdoch if (should_normalize) { 697086aeeaae12517475c22695a200be45495516549Ben Murdoch __ CompareRoot(rax, Heap::kTrueValueRootIndex); 698086aeeaae12517475c22695a200be45495516549Ben Murdoch Split(equal, if_true, if_false, NULL); 699086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&skip); 700086aeeaae12517475c22695a200be45495516549Ben Murdoch } 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The variable in the declaration always resides in the current context. 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); 707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we're not inside a with or catch context. 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_equal, kDeclarationInWithContext); 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_equal, kDeclarationInCatchContext); 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration( 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* declaration) { 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = proxy->var(); 722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::UNALLOCATED: { 724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(!variable->binding_needs_init()); 72562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(variable->name(), zone()); 72662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot = proxy->VariableFeedbackSlot(); 727f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!slot.IsInvalid()); 728f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch globals_->Add(isolate()->factory()->undefined_value(), zone()); 73062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(isolate()->factory()->undefined_value(), zone()); 731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: 735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (variable->binding_needs_init()) { 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 73769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackOperand(variable), kScratchRegister); 739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 74069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: 743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (variable->binding_needs_init()) { 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 74669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(ContextOperand(rsi, variable->index()), kScratchRegister); 74869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // No write barrier since the hole value is in old space. 749bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 75069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 75169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 75362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case VariableLocation::LOOKUP: 754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration( 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionDeclaration* declaration) { 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::UNALLOCATED: { 76662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(variable->name(), zone()); 76762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot = proxy->VariableFeedbackSlot(); 76862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!slot.IsInvalid()); 76962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We need the slot where the literals array lives, too. 77262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch slot = declaration->fun()->LiteralFeedbackSlot(); 773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(!slot.IsInvalid()); 774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 77562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function = 777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for stack-overflow exception. 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_null()) return SetStackOverflow(); 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(function, zone()); 78169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: { 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackOperand(variable), result_register()); 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: { 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(ContextOperand(rsi, variable->index()), result_register()); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(variable->index()); 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a function, which is not a smi. 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(rsi, 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset, 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_register(), 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 806bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 81062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case VariableLocation::LOOKUP: 811f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 8183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(Smi::FromInt(DeclareGlobalsFlags())); 82162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(rax); 822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(rax); 823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals); 8243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 8253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 8263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 828f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 831f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 832086aeeaae12517475c22695a200be45495516549Ben Murdoch 833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 8340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 835bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS); 836f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 8448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clause->body_target()->Unuse(); 8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 852f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 8570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 85980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rsp, 0)); // Switch value. 8610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 8621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 8630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rdx); 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(rcx, rax); 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 8681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rax); 87080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &next_test); 87180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 8728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(clause->body_target()); 87380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 87480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 8761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position before stub call for type feedback. 877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(clause); 878109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> ic = 879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, clause->CompareId()); 8813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 8821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&skip, Label::kNear); 885bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(clause, BailoutState::TOS_REGISTER); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kTrueValueRootIndex); 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &next_test); 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(clause->body_target()); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 8958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(clause->body_target()); 896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(1); // Switch value is no longer needed. 902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 90369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(nested_statement.break_label()); 904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 9058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(default_clause->body_target()); 906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 9128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(clause->body_target()); 913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS); 914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 91769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(nested_statement.break_label()); 918bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS); 919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 922f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetStatementPosition(stmt, SKIP_BREAK); 925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 92662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot = stmt->ForInFeedbackSlot(); 927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Get the object to enumerate over. 929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionAsStatementPosition(stmt->enumerable()); 9300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 9313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch OperandStackDepthIncrement(5); 9323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 9333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Label loop, exit; 9343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Iteration loop_statement(this, stmt); 9353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch increment_loop_depth(); 9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 937109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // If the object is null or undefined, skip over the loop, otherwise convert 938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // it to a JS receiver. See ECMA-262 version 5, section 12.6.4. 939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(rax, &convert, Label::kNear); 941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx); 942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above_equal, &done_convert, Label::kNear); 943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(rax, Heap::kNullValueRootIndex); 944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &exit); 945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &exit); 947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 948c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET); 949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 950f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 951bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER); 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 954bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check cache validity in generated code. If we cannot guarantee cache 955bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // validity, call the runtime system to check cache validity or get the 956bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // property names in a fixed array. Note: Proxies never have an enum cache, 957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // so will always take the slow path. 958109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label call_runtime; 959109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CheckEnumCache(&call_runtime); 960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The enum cache is valid. Load the map of the object being 962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // iterated over and use the cache for the iteration. 963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label use_cache; 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&use_cache, Label::kNear); 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call_runtime); 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Duplicate the enumerable object on the stack. 970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kForInEnumerate); 971bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER); 972f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fixed_array; 977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::kMetaMapRootIndex); 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &fixed_array); 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register rax. Get the enumeration cache from it. 982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&use_cache); 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_descriptors; 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLength(rdx, rax); 987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Cmp(rdx, Smi::kZero); 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &no_descriptors); 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(rax, rcx); 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset)); 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the four remaining stack slots. 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Map. 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); // Enumeration cache. 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); // Number of valid entries for the map in the enum cache. 998c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(Smi::kZero); // Initial index. 999f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_descriptors); 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kPointerSize)); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&exit); 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register rax. Iterate through that. 1006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Smi::FromInt(1)); // Smi(1) indicates slow check 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Array 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Fixed array length (as smi). 1013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS); 1014c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(Smi::kZero); // Initial index. 1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 1017f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionAsStatementPosition(stmt->each()); 1019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 102269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, loop_statement.break_label()); 1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Get the current entry of the array into register rax. 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rsp, 2 * kPointerSize)); 1026f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); 1027f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ movp(rax, 1028f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FieldOperand(rbx, index.reg, index.scale, FixedArray::kHeaderSize)); 1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the expected map from the stack or a smi in the 1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register rdx. 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rsp, 3 * kPointerSize)); 1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not, we may have to filter the key. 1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label update_each; 1037f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ movp(rbx, Operand(rsp, 4 * kPointerSize)); 1038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ cmpp(rdx, FieldOperand(rbx, HeapObject::kMapOffset)); 1039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &update_each, Label::kNear); 1040f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // We need to filter the key, record slow-path here. 10423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch int const vector_index = SmiFromSlot(slot)->value(); 104362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(rdx); 1044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(FieldOperand(rdx, FixedArray::OffsetOfElementAt(vector_index)), 104562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackVector::MegamorphicSentinel(isolate())); 1046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1047c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // rax contains the key. The receiver in rbx is the second argument to 1048c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // ForInFilter. ForInFilter returns undefined if the receiver doesn't 1049f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // have the key or returns the name-converted key. 1050c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET); 1051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 1052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER); 1053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfRoot(result_register(), Heap::kUndefinedValueRootIndex, 1054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch loop_statement.continue_label()); 1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // entry in register rax. 1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { EffectContext context(this); 1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitAssignment(stmt->each(), stmt->EachFeedbackSlot()); 1062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS); 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body(). 1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS); 1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1069f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1070f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.continue_label()); 1073f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS); 1074f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); 1075f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, &loop); 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(&loop); 1078f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.break_label()); 10813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DropOperands(5); 1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1083f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 1084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS); 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1086f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 10883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, 109062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot) { 1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NeedsHomeObject(initializer)); 1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(StoreDescriptor::ValueRegister(), 1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand(rsp, offset * kPointerSize)); 1095f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, isolate()->factory()->home_object_symbol()); 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, 1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset, 110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot) { 1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(NeedsHomeObject(initializer)); 1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(StoreDescriptor::ReceiverRegister(), rax); 1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(StoreDescriptor::ValueRegister(), 1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Operand(rsp, offset * kPointerSize)); 1105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, isolate()->factory()->home_object_symbol()); 1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, 1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeofMode typeof_mode) { 11103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Record position before possible IC call. 1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(proxy); 1112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); 11133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Variable* var = proxy->var(); 11143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 111562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Two cases: global variable, and all other types of variables. 1116589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::UNALLOCATED: { 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Global variable"); 1119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitGlobalVariableLoad(proxy, typeof_mode); 1120589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(rax); 1121589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1122589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 112359151504615d929945dc59db37bf1166937748c6Steve Block 1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::PARAMETER: 1125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::LOCAL: 1126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case VariableLocation::CONTEXT: { 1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : "[ Stack slot"); 1130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { 1131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Throw a reference error when using an uninitialized let/const 1132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // binding in harmony mode. 1133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(IsLexicalVariableMode(var->mode())); 1134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GetVar(rax, var); 1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &done, Label::kNear); 1138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(var->name()); 1139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(rax); 1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 1143589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(var); 1145589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1146589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case VariableLocation::LOOKUP: 1149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case VariableLocation::MODULE: 1150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch UNREACHABLE(); 11513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 11543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { 1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* expression = (property == NULL) ? NULL : property->value(); 11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expression == NULL) { 1158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(1); 11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kNullValueRootIndex); 11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(expression); 1162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(expression)) { 1163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->kind() == ObjectLiteral::Property::GETTER || 1164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch property->kind() == ObjectLiteral::Property::SETTER); 1165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3; 1166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(expression, offset, property->GetSlot()); 1167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<BoilerplateDescription> constant_properties = 117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch expr->GetOrBuildConstantProperties(isolate()); 1177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int flags = expr->ComputeFlags(); 1178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (MustCreateObjectLiteralWithRuntime(expr)) { 1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 118062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(SmiFromSlot(expr->literal_slot())); 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(constant_properties); 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(flags)); 1183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateObjectLiteral); 11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 118662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Move(rbx, SmiFromSlot(expr->literal_slot())); 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rcx, constant_properties); 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rdx, Smi::FromInt(flags)); 118962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = CodeFactory::FastCloneShallowObject( 119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate(), expr->properties_count()); 119162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 1192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); 1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1196e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorTable accessor_table(zone()); 120162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (int i = 0; i < expr->properties()->length(); i++) { 120262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ObjectLiteral::Property* property = expr->properties()->at(i); 120362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!property->is_computed_name()); 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Literal* key = property->key()->AsLiteral(); 1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1209109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(rax); // Save result on the stack 1210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 121362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case ObjectLiteral::Property::SPREAD: 1214e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 1215e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1216e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); 1218e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // It is safe to use [[Put]] here because the boilerplate already 1221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // contains computed properties with an uninitialized value. 1222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (key->IsStringLiteral()) { 1223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(key->IsPropertyName()); 12243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1225053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block VisitForAccumulatorValue(value); 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(rax)); 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); 122862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CallStoreIC(property->GetSlot(0), key->value(), true); 1229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); 1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (NeedsHomeObject(value)) { 1232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); 1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 1234053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 1235053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block VisitForEffect(value); 12363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Operand(rsp, 0)); // Duplicate receiver. 12400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 12410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 12423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (NeedsHomeObject(value)) { 1244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitSetHomeObject(value, 2, property->GetSlot()); 1245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1246109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(SLOPPY)); // Language mode 1247109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kSetProperty); 12483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 1249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DropOperands(3); 12503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::PROTOTYPE: 1253109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Operand(rsp, 0)); // Duplicate receiver. 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(value); 1255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(property->emit_store()); 1256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kInternalSetPrototype); 125762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch PrepareForBailoutForId(expr->GetIdForPropertySet(i), 1258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 126085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch case ObjectLiteral::Property::GETTER: 1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 126213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AccessorTable::Iterator it = accessor_table.lookup(key); 126362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch it->second->bailout_id = expr->GetIdForPropertySet(i); 126413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->getter = property; 1265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case ObjectLiteral::Property::SETTER: 1268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (property->emit_store()) { 126913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch AccessorTable::Iterator it = accessor_table.lookup(key); 127062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch it->second->bailout_id = expr->GetIdForPropertySet(i); 127113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch it->second->setter = property; 1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // each pair of corresponding getters and setters. 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it != accessor_table.end(); 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++it) { 1282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Operand(rsp, 0)); // Duplicate receiver. 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(it->first); 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->getter); 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->setter); 1286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Smi::FromInt(NONE)); 1287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked); 128813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS); 1289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 12920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 12940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 12953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 12963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 12973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1299d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 13003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 130262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<ConstantElementsPair> constant_elements = 130362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch expr->GetOrBuildConstantElements(isolate()); 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (MustCreateArrayLiteralWithRuntime(expr)) { 1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 130762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(SmiFromSlot(expr->literal_slot())); 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(constant_elements); 1309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Smi::FromInt(expr->ComputeFlags())); 1310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateArrayLiteral); 1311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 131362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Move(rbx, SmiFromSlot(expr->literal_slot())); 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rcx, constant_elements); 131562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Callable callable = 131662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::FastCloneShallowArray(isolate(), TRACK_ALLOCATION_SITE); 131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(callable.code(), RelocInfo::CODE_TARGET); 1318f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch RestoreContext(); 13193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); 13213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 1323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* subexprs = expr->values(); 1324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int length = subexprs->length(); 13253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 13273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (int array_index = 0; array_index < length; array_index++) { 1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Expression* subexpr = subexprs->at(array_index); 1330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!subexpr->IsSpread()); 1331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 13323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 13333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 13353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 1337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(rax); // array literal 13383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 13393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 13413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(StoreDescriptor::NameRegister(), Smi::FromInt(array_index)); 1343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1344f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->LiteralFeedbackSlot()); 1345086aeeaae12517475c22695a200be45495516549Ben Murdoch 1346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(array_index), 1347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 13483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 13510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1352e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 13530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 13543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 13553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1358402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1361402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1362f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(property); 1365402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1366402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1368402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1370402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1371402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1372402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need the receiver both on the stack and in the register. 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1376402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 13770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1378402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1379402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1380086aeeaae12517475c22695a200be45495516549Ben Murdoch case KEYED_PROPERTY: { 1381f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->is_compound()) { 13823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize)); 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0)); 1386f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 13873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 13883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->key()); 1389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1390402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1391086aeeaae12517475c22695a200be45495516549Ben Murdoch } 139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 139362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 139462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1397402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 13988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // For compound assignments we need another deoptimization point after the 13998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // variable/property load. 1400402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 14010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 14020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 14030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 14043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 1405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER); 14060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 14070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 14080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 1409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 14110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 14120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 14130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 1414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(property->LoadId(), 1415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 14160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 141762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 141962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 14210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1422402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1423402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 1425109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(rax); // Left operand goes on the stack. 1426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(expr->value()); 1427402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 14280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 142980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 1430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 143180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 143280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 1433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch expr->value()); 143480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitBinaryOp(expr->binary_operation(), op); 143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1437086aeeaae12517475c22695a200be45495516549Ben Murdoch // Deoptimization point in case the binary operation may have side effects. 1438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER); 143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 14400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 1444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1445402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case VARIABLE: { 1448c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->target()->AsVariableProxy(); 1449c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), 1450c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 1451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1454c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1455402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1456402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 146462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1465402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1466402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1467402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1468402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) { 147062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Resumable functions are not supported. 147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::PushOperand(MemOperand operand) { 1475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(1); 1476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(operand); 1477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1479109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid FullCodeGenerator::EmitOperandStackDepthCheck() { 1480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_debug_code) { 1481109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + 1482109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch operand_stack_depth_ * kPointerSize; 1483109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movp(rax, rbp); 1484109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ subp(rax, rsp); 1485109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmpp(rax, Immediate(expected_diff)); 1486109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Assert(equal, kUnexpectedStackDepth); 1487109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1488109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) { 1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label allocate, done_allocate; 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, 1494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done_allocate, Label::kNear); 1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&allocate); 1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(Smi::FromInt(JSIteratorResult::kSize)); 1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace); 1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_allocate); 1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx); 1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); 1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); 1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); 1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); 1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset), 1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); 1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); 15113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch OperandStackDepthDecrement(1); 1512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 151680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 151780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 1518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Expression* right) { 151980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do combined smi check of the operands. Left operand is on the 152080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // stack (popped into rdx). Right operand is in rax but moved into 152180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx to make the shifts easier. 1522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, stub_call, smi_case; 1523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(rdx); 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rax); 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(rax, rdx); 15261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 1527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 152880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 152980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&stub_call); 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rcx); 1531109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 15333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 153580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 153680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 153780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 153880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 153980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftArithmeticRight(rax, rdx, rcx); 154080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 154180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiShiftLeft(rax, rdx, rcx, &stub_call); 154380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 154480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: 154580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call); 154680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 154780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::ADD: 154880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAdd(rax, rdx, rcx, &stub_call); 154980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 155080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SUB: 155180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiSub(rax, rdx, rcx, &stub_call); 155280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::MUL: 155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiMul(rax, rdx, rcx, &stub_call); 155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 155780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiOr(rax, rdx, rcx); 155880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 155980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 156080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAnd(rax, rdx, rcx); 156180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 156280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 156380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiXor(rax, rdx, rcx); 156480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 156580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 156680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 15710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { 1576109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(rdx); 1577109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); 15783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 15803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 15810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 158462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr, FeedbackSlot slot) { 1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->IsValidReferenceExpressionOrThis()); 1586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1587f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(prop); 1589f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1590f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 1592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->AsVariableProxy(); 15930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 1594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, 1595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 1596f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 1599109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(rax); // Preserve value. 16000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::ReceiverRegister(), rax); 1602109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ValueRegister()); // Restore value. 1603f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, prop->key()->AsLiteral()->value()); 1604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1605f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1606f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 1607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(rax); // Preserve value. 16083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 16093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), rax); 1611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 1612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ValueRegister()); // Restore value. 1613f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(slot); 1614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 1615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 161662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 161762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 161862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 161962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 1620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1622f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1623f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1624f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var, MemOperand location) { 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(location, rax); 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rax); 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, 163662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackSlot slot, 1637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch HoleCheckMode hole_check_mode) { 1638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 1639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Global var, const, or let. 1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); 1641f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(slot, var->name()); 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1643f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsLookupSlot()); 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, rcx); 1647f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Perform an initialization check for lexically declared variables. 1648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (hole_check_mode == HoleCheckMode::kRequired) { 1649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label assign; 1650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ movp(rdx, location); 1651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ j(not_equal, &assign, Label::kNear); 1653f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(var->name()); 1654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&assign); 1656f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (var->mode() != CONST) { 1658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 1659f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else if (var->throw_on_const_assignment(language_mode())) { 1660f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ CallRuntime(Runtime::kThrowConstAssignError); 1661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { 1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Initializing assignment to const {this} needs a write barrier. 1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label uninitialized_this; 1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MemOperand location = VarOperand(var, rcx); 1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rdx, location); 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &uninitialized_this); 1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(var->name()); 1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowReferenceError); 1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&uninitialized_this); 1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1676f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 1677f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK(var->mode() != CONST || op == Token::INIT); 167862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 167962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!var->IsLookupSlot()); 168062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Assignment to var or initializing assignment to let/const in harmony 168162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // mode. 168262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MemOperand location = VarOperand(var, rcx); 168362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { 168462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check for an uninitialized let binding. 168562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ movp(rdx, location); 168662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 168762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Check(equal, kLetBindingReInitialization); 16883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 168962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 16903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 16913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 16923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 16933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1694d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 1696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop != NULL); 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->key()->IsLiteral()); 1699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 1701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value()); 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1703bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 1710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::NameRegister()); // Key. 1711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(rax)); 1713f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->AssignmentSlot()); 1714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 1716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(rax); 1717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the target function. 1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ConvertReceiverMode convert_mode; 1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (callee->IsVariableProxy()) { 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { StackValueContext context(this); 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(callee->AsVariableProxy()); 1728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(callee, BailoutState::NO_REGISTERS); 17293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push undefined as receiver. This is patched in the Call builtin if it 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a sloppy mode method. 1732109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(isolate()->factory()->undefined_value()); 1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch convert_mode = ConvertReceiverMode::kNullOrUndefined; 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!callee->AsProperty()->IsSuperAccess()); 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(callee->AsProperty()); 1740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), 1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 1743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Operand(rsp, 0)); 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 1745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch convert_mode = ConvertReceiverMode::kNotNullOrUndefined; 17463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr, convert_mode); 1749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1750d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Common code for calls using the IC. 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key) { 17558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 17568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 17578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 17598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), rax); 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(callee->AsProperty()); 1765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), 1766bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 1769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Operand(rsp, 0)); 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); 17739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 17749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 17759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) { 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments. 1778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < arg_count; i++) { 1781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(i)); 1782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS); 17853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SetCallPosition(expr, expr->tail_call_mode()); 1786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (expr->tail_call_mode() == TailCallMode::kAllow) { 1787109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (FLAG_trace) { 1788109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kTraceTailCall); 1789109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Update profiling counters before the tail call since we will 1791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // not return to this function. 1792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch EmitProfilingCounterHandlingForReturnSequence(true); 1793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Handle<Code> code = 179562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CodeFactory::CallICTrampoline(isolate(), mode, expr->tail_call_mode()) 179662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch .code(); 179762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Set(rdx, IntFromSlot(expr->CallFeedbackICSlot())); 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 1799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Set(rax, arg_count); 1800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallIC(code); 1801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1803086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 1804bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 18053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 18060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 1807d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1808d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 1810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 1811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 1812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 1813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 1814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 181580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 181680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 181780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 1818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!expr->expression()->IsSuperPropertyReference()); 1819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(expr->expression()); 1820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 1822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 1823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 1824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 18250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 18263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 1827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 1829d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetConstructCallPosition(expr); 1831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 183280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into rdi and rax. 1833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsp, arg_count * kPointerSize)); 1835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record call targets in unoptimized code, but not in the snapshot. 183762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(rbx); 1838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ Move(rdx, SmiFromSlot(expr->CallNewFeedbackSlot())); 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CallConstructStub stub(isolate()); 1841c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch CallIC(stub.GetCode()); 1842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 1843bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER); 1844bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 18450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 18463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 18520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1853f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1854f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1855f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1856f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 18580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 18590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(rax, if_true); 1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(if_false); 1864f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 18650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1866f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) { 18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 18723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 18730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 18743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 18753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 18763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 18773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 187880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 18790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 18800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 18813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 18823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ JumpIfSmi(rax, if_false); 1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rbx); 18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 188580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(above_equal, if_true, if_false, fall_through); 18863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 18870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 18883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 18893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 18903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 18950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 190080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 1903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 1905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 190780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 1908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1911f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) { 19143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1916f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1918f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1920f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1921f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 192280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, &if_true, 1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_false, &fall_through); 1925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rax, JS_TYPED_ARRAY_TYPE, rbx); 19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 192980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 1930f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1932f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) { 1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(args->length() == 1); 1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(args->at(0)); 1940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 1942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 1943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 194480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->PrepareTest(&materialize_true, &materialize_false, &if_true, 1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &if_false, &fall_through); 1947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(rax, if_false); 1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rax, JS_PROXY_TYPE, rbx); 19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 195280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 1953f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 1955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1956f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 1961f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 1962f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 19630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 1964f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the object is not a JSReceiver, we return null. 1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(rax, &null, Label::kNear); 1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax); 1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &null, Label::kNear); 1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 19713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Return 'Function' for JSFunction and JSBoundFunction objects. 19723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ CmpInstanceType(rax, FIRST_FUNCTION_TYPE); 19733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); 19743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(above_equal, &function, Label::kNear); 19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the constructor in the map is a JS function. 1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetMapConstructor(rax, rax, rbx); 1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(rbx, JS_FUNCTION_TYPE); 1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &non_function_constructor, Label::kNear); 1980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1981f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rax now contains the constructor function. Grab the 1982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Non-JS objects have class null. 1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&null); 1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(rax, Heap::kNullValueRootIndex); 1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 1991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 1993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 1994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(rax, Heap::kFunction_stringRootIndex); 1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 1998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 1999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(rax, Heap::kObject_stringRootIndex); 2000f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 2002f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 2003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2006f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2007f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 20117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 20120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 20130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 20147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 20157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 20167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 20177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rdx; 20187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(object); 20207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 20217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 20227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 20237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 202413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch StringCharCodeAtGenerator generator(object, index, result, &need_conversion, 202513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch &need_conversion, &index_out_of_range); 20267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 2027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 2028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 20297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 20307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 20317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 20327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 20337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 20347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 20357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 20367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move the undefined value into the result register, which will 20377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 20387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 20397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 20407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 20417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper); 2043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 20450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 2046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCall(CallRuntime* expr) { 20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_LE(2, args->length()); 2052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push target, receiver and arguments onto the stack. 2053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (Expression* const arg : *args) { 2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(arg); 2055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2056bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS); 2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Move target to rdi. 2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const argc = args->length() - 2; 2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rdi, Operand(rsp, (argc + 1) * kPointerSize)); 2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the target. 2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Set(rax, argc); 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 2063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(argc + 1); 2064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Discard the function left on TOS. 2066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->DropAndPlug(1, rax); 2067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2068f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) { 2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(1, args->length()); 2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(args->at(0)); 2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(rax); 2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, FieldOperand(rax, Map::kPrototypeOffset)); 2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(rax); 2077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference debug_is_active = 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::debug_is_active_address(isolate()); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, debug_is_active); 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(rax, Operand(kScratchRegister, 0)); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rax, rax); 208644f0eee88ff00398ff7f715fab053374d808c90dSteve Block context()->Plug(rax); 20878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 20888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 20898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { 2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(2, args->length()); 2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(0)); 2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForStackValue(args->at(1)); 2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label runtime, done; 2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime, 2099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch NO_ALLOCATION_FLAGS); 2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx); 2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); 2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); 2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); 2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); 2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset)); 2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); 2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); 2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&runtime); 2111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(Runtime::kCreateIterResultObject); 2112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(rax); 2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { 21193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push function. 21203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ LoadNativeContextSlot(expr->context_index(), rax); 21213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch PushOperand(rax); 21223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 21233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Push undefined as receiver. 2124109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthIncrement(1); 2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2128f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { 2130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 2131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int arg_count = args->length(); 2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetCallPosition(expr); 2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Set(rax, arg_count); 2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch OperandStackDepthDecrement(arg_count + 1); 2139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RestoreContext(); 2140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 2144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 2145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 2146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 2147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = expr->expression()->AsProperty(); 2148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2150589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property != NULL) { 2151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 2152589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->key()); 2153109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CallRuntimeWithOperands(is_strict(language_mode()) 2154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ? Runtime::kDeleteProperty_Strict 2155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Runtime::kDeleteProperty_Sloppy); 215669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(rax); 2157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 2158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Delete of an unqualified identifier is disallowed in strict mode but 2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // "delete this" is allowed. 2161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool is_this = var->is_this(); 2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(is_sloppy(language_mode()) || is_this); 2163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (var->IsUnallocated()) { 2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, NativeContextOperand()); 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(ContextOperand(rax, Context::EXTENSION_INDEX)); 2166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(var->name()); 2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kDeleteProperty_Sloppy); 2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(rax); 216962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else { 217062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!var->IsLookupSlot()); 217162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-global variables is false. 'this' is 2173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // not really a variable, though we implement it as one. The 2174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // subexpression does not have side effects. 2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch context()->Plug(is_this); 2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 21771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-property, non-variable reference is true. 2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression may have side effects. 2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(true); 2182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 2187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 2188e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 21890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 2190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 2194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 2195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (context()->IsEffect()) { 2196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression. Match the optimizing compiler by not branching. 2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context()->IsTest()) { 22003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const TestContext* test = TestContext::cast(context()); 22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The labels are swapped for the recursive call. 22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->false_label(), 22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->true_label(), 22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->fall_through()); 22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(test->true_label(), test->false_label()); 2207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We handle value contexts explicitly rather than simply visiting 22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for control and plugging the control flow into the context, 22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // because we need to prepare a pair of extra administrative AST ids 22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for the optimizing compiler. 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); 22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false, done; 22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_false, 22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true, 22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true); 2218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1); 22193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_true); 2220bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), 2221bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsAccumulatorValue()) { 22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kTrueValueRootIndex); 22263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_false); 2229bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), 2230bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::NO_REGISTERS); 22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsAccumulatorValue()) { 22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kFalseValueRootIndex); 22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 2237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 2242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 2243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch AccumulatorValueContext context(this); 22450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 22460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rbx, rax); 2248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET); 22490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2252d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 2254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 22553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 22563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 22573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 22583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2259d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2262e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 2263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 2265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LhsKind assign_type = Property::GetAssignType(prop); 2266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 2268e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 22700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 22713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 2272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 22740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 2275c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch PushOperand(Smi::kZero); 2276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (assign_type) { 2278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case NAMED_PROPERTY: { 2279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->obj()); 2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 2281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitNamedPropertyLoad(prop); 2282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_PROPERTY: { 2286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->obj()); 2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier VisitForStackValue(prop->key()); 2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Leave receiver on stack 2289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize)); 2290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Copy of key, needed for later store. 2291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0)); 2292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier EmitKeyedPropertyLoad(prop); 2293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 229662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 229762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 2298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case VARIABLE: 2299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier UNREACHABLE(); 2300e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2303086aeeaae12517475c22695a200be45495516549Ben Murdoch // We need a second deoptimization point after loading the value 2304086aeeaae12517475c22695a200be45495516549Ben Murdoch // in case evaluating the property load my have a side effect. 23058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (assign_type == VARIABLE) { 2306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER); 23078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 2308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER); 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline smi case if we are in a loop. 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, stub_call; 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(expr->op())) { 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear); 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we store the result under the receiver that is currently on top 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the stack. 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 2 * kPointerSize), rax); 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 233462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 2335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 233662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiOperationConstraints constraints = 2343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiOperationConstraint::kPreserveSourceRegister | 2344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SmiOperationConstraint::kBailoutOnNoOverflow; 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->op() == Token::INC) { 2346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiAddConstant(rax, rax, Smi::FromInt(1), constraints, &done, 2347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear); 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiSubConstant(rax, rax, Smi::FromInt(1), constraints, &done, 2350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear); 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&stub_call, Label::kNear); 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 23548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 23553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch 23563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Convert old value into a number. 235713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 2358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RestoreContext(); 2359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER); 2360e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 2362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 23630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 23640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 23650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 23660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 23670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 23680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 2369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(rax); 23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 23710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 23730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 23740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 2 * kPointerSize), rax); 23760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 237762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 2378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier case KEYED_SUPER_PROPERTY: 237962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 2380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier break; 23810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2382e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetExpressionPosition(expr); 2386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2387e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stub_call); 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rax); 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, Smi::FromInt(1)); 2391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> code = 2392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code(); 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->CountBinOpFeedbackId()); 23943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 2395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 2396e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2397e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 2398e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 2399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch case VARIABLE: { 2400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 2401e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 24030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 2404c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), 2405c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 2406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), 2407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Plug(rax); 24090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 2411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 24120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 24130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 2414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2415e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 2417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), 2418c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch proxy->hole_check_mode()); 2419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), 2420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch BailoutState::TOS_REGISTER); 2421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 2425e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 2426109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 2427f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); 2428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 2429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 24300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 24310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 2432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 24340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 2439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::NameRegister()); 2440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(StoreDescriptor::ReceiverRegister()); 2441f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch CallKeyedStoreIC(expr->CountSlot()); 2442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); 2443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 24440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 24450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 2446e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2447e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 24480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 2451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 245262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case NAMED_SUPER_PROPERTY: 245362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch case KEYED_SUPER_PROPERTY: 245462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch UNREACHABLE(); 245562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch break; 2456e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 2457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 24603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 24623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check) { 24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false; 24643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_true = NULL; 24653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_false = NULL; 24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fall_through = NULL; 24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &if_true, &if_false, &fall_through); 24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForTypeofValue(sub_expr); 24720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 24740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(check, factory->number_string())) { 2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_true); 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 247980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 248080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->string_string())) { 2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 2484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(below, if_true, if_false, fall_through); 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->symbol_string())) { 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rax, if_false); 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rax, SYMBOL_TYPE, rdx); 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(equal, if_true, if_false, fall_through); 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->boolean_string())) { 249080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kTrueValueRootIndex); 2491f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 249280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kFalseValueRootIndex); 249380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->undefined_string())) { 2495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CompareRoot(rax, Heap::kNullValueRootIndex); 2496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, if_false); 2497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 249880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 250080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 250180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 250280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->function_string())) { 2504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 2505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for callable and not undetectable objects => true. 2506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 2507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movzxbl(rdx, FieldOperand(rdx, Map::kBitFieldOffset)); 2508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ andb(rdx, 2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); 2510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmpb(rdx, Immediate(1 << Map::kIsCallable)); 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Split(equal, if_true, if_false, fall_through); 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->object_string())) { 2513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kNullValueRootIndex); 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, if_true); 2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rdx); 2518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(below, if_false); 2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for callable or undetectable objects => false. 252080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 2521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable))); 2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(zero, if_true, if_false, fall_through); 252380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 252480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 2525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(if_true, if_false); 2527f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 2531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 2532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 25333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First we try a fast inlined version of the compare when one of 25343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the operands is a literal. 25353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryLiteralCompare(expr)) return; 25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 2538e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 2539f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2540f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 254280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 25430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 25440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 254580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 25463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = expr->op(); 25470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 254880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 2549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 25500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 2551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 2552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch EmitHasProperty(); 25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 2554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 255580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 2556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 25573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VisitForAccumulatorValue(expr->right()); 2560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 2561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(rdx); 2562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET); 256362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RestoreContext(); 2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(rax, Heap::kTrueValueRootIndex); 2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Split(equal, if_true, if_false, fall_through); 2567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 2568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 25710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 2572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetExpressionPosition(expr); 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cc = CompareIC::ComputeCondition(op); 2574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PopOperand(rdx); 2575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 25760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 25771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 25780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 2579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rdx); 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(rcx, rax); 2582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rax); 258480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, NULL); 258580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 258680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 2587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 25903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 2591086aeeaae12517475c22695a200be45495516549Ben Murdoch 25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 259480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, fall_through); 2595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 25963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 25973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 2599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 26000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 26043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 260780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 260880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 260980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 261080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 26110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 26120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 261380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 26143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(sub_expr); 26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::EQ_STRICT) { 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kNullValueRootIndex : 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kUndefinedValueRootIndex; 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, nil_value); 262180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 262280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 26233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ JumpIfSmi(rax, if_false); 26243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 26253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ testb(FieldOperand(rax, Map::kBitFieldOffset), 26263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsUndetectable)); 26273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Split(not_zero, if_true, if_false, fall_through); 262880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 26290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 263080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 263180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 263280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 26330d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 26340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rax; 26350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 2636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 26380d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 26390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rsi; 26400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 26410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 26423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) { 26433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK(IsAligned(frame_offset, kPointerSize)); 26443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ movp(value, Operand(rbp, frame_offset)); 26453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch} 26460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 2647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAligned(frame_offset, kPointerSize)); 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rbp, frame_offset), value); 26503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 26513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 26523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2653d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(dst, ContextOperand(rsi, context_index)); 2655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 26583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 2659f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DeclarationScope* closure_scope = scope()->GetClosureScope(); 2660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (closure_scope->is_script_scope() || 2661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch closure_scope->is_module_scope()) { 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts nested in the native context have a canonical empty function 26633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // as their closure, not the anonymous closure containing the global 2664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // code. 2665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movp(rax, NativeContextOperand()); 2666109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ContextOperand(rax, Context::CLOSURE_INDEX)); 2667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (closure_scope->is_eval_scope()) { 26683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts created by a call to eval have the same closure as the 26693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // context calling eval, not the anonymous closure containing the eval 26703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Fetch it from the context. 2671109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(ContextOperand(rsi, Context::CLOSURE_INDEX)); 26723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(closure_scope->is_function_scope()); 2674109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PushOperand(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 26753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 26763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 26773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 267969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __ 2680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsInstruction = 0x79; 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteOne = 0x66; 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteTwo = 0x90; 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kCallInstruction = 0xe8; 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code, 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc, 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BackEdgeState target_state, 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* replacement_code) { 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address call_target_address = pc - kIntSize; 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address jns_instr_address = call_target_address - 3; 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address jns_offset_address = call_target_address - 2; 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (target_state) { 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INTERRUPT: 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sub <profiling_counter>, <delta> ;; Not changed 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jns ok 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call <interrupt stub> 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok: 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_instr_address = kJnsInstruction; 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_offset_address = kJnsOffset; 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ON_STACK_REPLACEMENT: 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sub <profiling_counter>, <delta> ;; Not changed 2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call <on-stack replacment> 2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok: 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_instr_address = kNopByteOne; 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_offset_address = kNopByteTwo; 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Assembler::set_target_address_at(unoptimized_code->GetIsolate(), 2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch call_target_address, unoptimized_code, 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch replacement_code->entry()); 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, call_target_address, replacement_code); 2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* unoptimized_code, 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc) { 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address call_target_address = pc - kIntSize; 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address jns_instr_address = call_target_address - 3; 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kCallInstruction, *(call_target_address - 1)); 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*jns_instr_address == kJnsInstruction) { 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kJnsOffset, *(call_target_address - 2)); 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(), 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::target_address_at(call_target_address, 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code)); 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INTERRUPT; 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kNopByteOne, *jns_instr_address); 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kNopByteTwo, *(call_target_address - 2)); 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch DCHECK_EQ( 27463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch isolate->builtins()->OnStackReplacement()->entry(), 27473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Assembler::target_address_at(call_target_address, unoptimized_code)); 27483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch return ON_STACK_REPLACEMENT; 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 2753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 2755