| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/ic/call-optimization.h" | 9 #include "src/ic/call-optimization.h" |
| 10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 DCHECK(cell->value()->IsTheHole()); | 208 DCHECK(cell->value()->IsTheHole()); |
| 209 Factory* factory = masm->isolate()->factory(); | 209 Factory* factory = masm->isolate()->factory(); |
| 210 Handle<WeakCell> weak_cell = factory->NewWeakCell(cell); | 210 Handle<WeakCell> weak_cell = factory->NewWeakCell(cell); |
| 211 __ LoadWeakValue(scratch, weak_cell, miss); | 211 __ LoadWeakValue(scratch, weak_cell, miss); |
| 212 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), factory->the_hole_value()); | 212 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), factory->the_hole_value()); |
| 213 __ j(not_equal, miss); | 213 __ j(not_equal, miss); |
| 214 } | 214 } |
| 215 | 215 |
| 216 | 216 |
| 217 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( | 217 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
| 218 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | 218 MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, |
| 219 Register holder, int accessor_index, int expected_arguments, | 219 int accessor_index, int expected_arguments, Register scratch) { |
| 220 Register scratch) { | |
| 221 // ----------- S t a t e ------------- | 220 // ----------- S t a t e ------------- |
| 222 // -- rsp[0] : return address | 221 // -- rsp[0] : return address |
| 223 // ----------------------------------- | 222 // ----------------------------------- |
| 224 { | 223 { |
| 225 FrameScope scope(masm, StackFrame::INTERNAL); | 224 FrameScope scope(masm, StackFrame::INTERNAL); |
| 226 | 225 |
| 227 // Save value register, so we can restore it later. | 226 // Save value register, so we can restore it later. |
| 228 __ Push(value()); | 227 __ Push(value()); |
| 229 | 228 |
| 230 if (accessor_index >= 0) { | 229 if (accessor_index >= 0) { |
| 231 DCHECK(!holder.is(scratch)); | 230 DCHECK(!holder.is(scratch)); |
| 232 DCHECK(!receiver.is(scratch)); | 231 DCHECK(!receiver.is(scratch)); |
| 233 DCHECK(!value().is(scratch)); | 232 DCHECK(!value().is(scratch)); |
| 234 // Call the JavaScript setter with receiver and value on the stack. | 233 // Call the JavaScript setter with receiver and value on the stack. |
| 235 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 234 if (map->IsJSGlobalObjectMap()) { |
| 236 // Swap in the global receiver. | 235 // Swap in the global receiver. |
| 237 __ movp(scratch, | 236 __ movp(scratch, |
| 238 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 237 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 239 receiver = scratch; | 238 receiver = scratch; |
| 240 } | 239 } |
| 241 __ Push(receiver); | 240 __ Push(receiver); |
| 242 __ Push(value()); | 241 __ Push(value()); |
| 243 ParameterCount actual(1); | 242 ParameterCount actual(1); |
| 244 ParameterCount expected(expected_arguments); | 243 ParameterCount expected(expected_arguments); |
| 245 __ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_SETTER); | 244 __ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_SETTER); |
| 246 __ InvokeFunction(rdi, expected, actual, CALL_FUNCTION, | 245 __ InvokeFunction(rdi, expected, actual, CALL_FUNCTION, |
| 247 NullCallWrapper()); | 246 NullCallWrapper()); |
| 248 } else { | 247 } else { |
| 249 // If we generate a global code snippet for deoptimization only, remember | 248 // If we generate a global code snippet for deoptimization only, remember |
| 250 // the place to continue after deoptimization. | 249 // the place to continue after deoptimization. |
| 251 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | 250 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
| 252 } | 251 } |
| 253 | 252 |
| 254 // We have to return the passed value, not the return value of the setter. | 253 // We have to return the passed value, not the return value of the setter. |
| 255 __ Pop(rax); | 254 __ Pop(rax); |
| 256 | 255 |
| 257 // Restore context register. | 256 // Restore context register. |
| 258 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 257 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 259 } | 258 } |
| 260 __ ret(0); | 259 __ ret(0); |
| 261 } | 260 } |
| 262 | 261 |
| 263 | 262 |
| 264 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | 263 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 265 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | 264 MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, |
| 266 Register holder, int accessor_index, int expected_arguments, | 265 int accessor_index, int expected_arguments, Register scratch) { |
| 267 Register scratch) { | |
| 268 // ----------- S t a t e ------------- | 266 // ----------- S t a t e ------------- |
| 269 // -- rax : receiver | 267 // -- rax : receiver |
| 270 // -- rcx : name | 268 // -- rcx : name |
| 271 // -- rsp[0] : return address | 269 // -- rsp[0] : return address |
| 272 // ----------------------------------- | 270 // ----------------------------------- |
| 273 { | 271 { |
| 274 FrameScope scope(masm, StackFrame::INTERNAL); | 272 FrameScope scope(masm, StackFrame::INTERNAL); |
| 275 | 273 |
| 276 if (accessor_index >= 0) { | 274 if (accessor_index >= 0) { |
| 277 DCHECK(!holder.is(scratch)); | 275 DCHECK(!holder.is(scratch)); |
| 278 DCHECK(!receiver.is(scratch)); | 276 DCHECK(!receiver.is(scratch)); |
| 279 // Call the JavaScript getter with the receiver on the stack. | 277 // Call the JavaScript getter with the receiver on the stack. |
| 280 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 278 if (map->IsJSGlobalObjectMap()) { |
| 281 // Swap in the global receiver. | 279 // Swap in the global receiver. |
| 282 __ movp(scratch, | 280 __ movp(scratch, |
| 283 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 281 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 284 receiver = scratch; | 282 receiver = scratch; |
| 285 } | 283 } |
| 286 __ Push(receiver); | 284 __ Push(receiver); |
| 287 ParameterCount actual(0); | 285 ParameterCount actual(0); |
| 288 ParameterCount expected(expected_arguments); | 286 ParameterCount expected(expected_arguments); |
| 289 __ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_GETTER); | 287 __ LoadAccessor(rdi, holder, accessor_index, ACCESSOR_GETTER); |
| 290 __ InvokeFunction(rdi, expected, actual, CALL_FUNCTION, | 288 __ InvokeFunction(rdi, expected, actual, CALL_FUNCTION, |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 } | 407 } |
| 410 __ bind(&do_store); | 408 __ bind(&do_store); |
| 411 } | 409 } |
| 412 } | 410 } |
| 413 | 411 |
| 414 | 412 |
| 415 Register PropertyHandlerCompiler::CheckPrototypes( | 413 Register PropertyHandlerCompiler::CheckPrototypes( |
| 416 Register object_reg, Register holder_reg, Register scratch1, | 414 Register object_reg, Register holder_reg, Register scratch1, |
| 417 Register scratch2, Handle<Name> name, Label* miss, | 415 Register scratch2, Handle<Name> name, Label* miss, |
| 418 PrototypeCheckType check) { | 416 PrototypeCheckType check) { |
| 419 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 417 Handle<Map> receiver_map = map(); |
| 420 | 418 |
| 421 // Make sure there's no overlap between holder and object registers. | 419 // Make sure there's no overlap between holder and object registers. |
| 422 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 420 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 423 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 421 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
| 424 !scratch2.is(scratch1)); | 422 !scratch2.is(scratch1)); |
| 425 | 423 |
| 426 // Keep track of the current object in register reg. On the first | 424 // Keep track of the current object in register reg. On the first |
| 427 // iteration, reg is an alias for object_reg, on later iterations, | 425 // iteration, reg is an alias for object_reg, on later iterations, |
| 428 // it is an alias for holder_reg. | 426 // it is an alias for holder_reg. |
| 429 Register reg = object_reg; | 427 Register reg = object_reg; |
| 430 int depth = 0; | 428 int depth = 0; |
| 431 | 429 |
| 432 Handle<JSObject> current = Handle<JSObject>::null(); | 430 Handle<JSObject> current = Handle<JSObject>::null(); |
| 433 if (type()->IsConstant()) { | 431 if (receiver_map->IsJSGlobalObjectMap()) { |
| 434 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 432 current = isolate()->global_object(); |
| 435 } | 433 } |
| 436 Handle<JSObject> prototype = Handle<JSObject>::null(); | 434 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 437 Handle<Map> current_map = receiver_map; | 435 Handle<Map> current_map = receiver_map; |
| 438 Handle<Map> holder_map(holder()->map()); | 436 Handle<Map> holder_map(holder()->map()); |
| 439 // Traverse the prototype chain and check the maps in the prototype chain for | 437 // Traverse the prototype chain and check the maps in the prototype chain for |
| 440 // fast and global objects or do negative lookup for normal objects. | 438 // fast and global objects or do negative lookup for normal objects. |
| 441 while (!current_map.is_identical_to(holder_map)) { | 439 while (!current_map.is_identical_to(holder_map)) { |
| 442 ++depth; | 440 ++depth; |
| 443 | 441 |
| 444 // Only global objects and objects that do not require access | 442 // Only global objects and objects that do not require access |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 // Return the generated code. | 755 // Return the generated code. |
| 758 return GetCode(kind(), Code::NORMAL, name); | 756 return GetCode(kind(), Code::NORMAL, name); |
| 759 } | 757 } |
| 760 | 758 |
| 761 | 759 |
| 762 #undef __ | 760 #undef __ |
| 763 } | 761 } |
| 764 } // namespace v8::internal | 762 } // namespace v8::internal |
| 765 | 763 |
| 766 #endif // V8_TARGET_ARCH_X64 | 764 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |