| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 28 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| 29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 29 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| 30 | 30 |
| 31 #include "assembler.h" | 31 #include "assembler.h" |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | 34 namespace internal { |
| 35 | 35 |
| 36 // ---------------------------------------------------------------------------- |
| 37 // Static helper functions |
| 38 |
| 39 // Generate a MemOperand for loading a field from an object. |
| 40 static inline MemOperand FieldMemOperand(Register object, int offset) { |
| 41 return MemOperand(object, offset - kHeapObjectTag); |
| 42 } |
| 43 |
| 36 | 44 |
| 37 // Give alias names to registers | 45 // Give alias names to registers |
| 38 const Register cp = { 8 }; // JavaScript context pointer | 46 const Register cp = { 8 }; // JavaScript context pointer |
| 39 | 47 const Register roots = { 10 }; // Roots array pointer. |
| 40 | 48 |
| 41 enum InvokeJSFlags { | 49 enum InvokeJSFlags { |
| 42 CALL_JS, | 50 CALL_JS, |
| 43 JUMP_JS | 51 JUMP_JS |
| 44 }; | 52 }; |
| 45 | 53 |
| 46 | 54 |
| 47 // MacroAssembler implements a collection of frequently used macros. | 55 // MacroAssembler implements a collection of frequently used macros. |
| 48 class MacroAssembler: public Assembler { | 56 class MacroAssembler: public Assembler { |
| 49 public: | 57 public: |
| 50 MacroAssembler(void* buffer, int size); | 58 MacroAssembler(void* buffer, int size); |
| 51 | 59 |
| 52 // --------------------------------------------------------------------------- | 60 // Jump, Call, and Ret pseudo instructions implementing inter-working. |
| 53 // Low-level helpers for compiler | |
| 54 | |
| 55 // Jump, Call, and Ret pseudo instructions implementing inter-working | |
| 56 private: | |
| 57 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | |
| 58 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); | |
| 59 public: | |
| 60 void Jump(Register target, Condition cond = al); | 61 void Jump(Register target, Condition cond = al); |
| 61 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al); | 62 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al); |
| 62 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); | 63 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); |
| 63 void Call(Register target, Condition cond = al); | 64 void Call(Register target, Condition cond = al); |
| 64 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al); | 65 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al); |
| 65 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); | 66 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); |
| 66 void Ret(Condition cond = al); | 67 void Ret(Condition cond = al); |
| 67 | 68 |
| 68 // Emit code to discard a non-negative number of pointer-sized elements | 69 // Emit code to discard a non-negative number of pointer-sized elements |
| 69 // from the stack, clobbering only the sp register. | 70 // from the stack, clobbering only the sp register. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 Register scratch2, | 203 Register scratch2, |
| 203 Label* gc_required, | 204 Label* gc_required, |
| 204 AllocationFlags flags); | 205 AllocationFlags flags); |
| 205 | 206 |
| 206 // Undo allocation in new space. The object passed and objects allocated after | 207 // Undo allocation in new space. The object passed and objects allocated after |
| 207 // it will no longer be allocated. The caller must make sure that no pointers | 208 // it will no longer be allocated. The caller must make sure that no pointers |
| 208 // are left to the object(s) no longer allocated as they would be invalid when | 209 // are left to the object(s) no longer allocated as they would be invalid when |
| 209 // allocation is undone. | 210 // allocation is undone. |
| 210 void UndoAllocationInNewSpace(Register object, Register scratch); | 211 void UndoAllocationInNewSpace(Register object, Register scratch); |
| 211 | 212 |
| 213 |
| 214 void AllocateTwoByteString(Register result, |
| 215 Register length, |
| 216 Register scratch1, |
| 217 Register scratch2, |
| 218 Register scratch3, |
| 219 Label* gc_required); |
| 220 void AllocateAsciiString(Register result, |
| 221 Register length, |
| 222 Register scratch1, |
| 223 Register scratch2, |
| 224 Register scratch3, |
| 225 Label* gc_required); |
| 226 void AllocateTwoByteConsString(Register result, |
| 227 Register length, |
| 228 Register scratch1, |
| 229 Register scratch2, |
| 230 Label* gc_required); |
| 231 void AllocateAsciiConsString(Register result, |
| 232 Register length, |
| 233 Register scratch1, |
| 234 Register scratch2, |
| 235 Label* gc_required); |
| 236 |
| 237 |
| 212 // --------------------------------------------------------------------------- | 238 // --------------------------------------------------------------------------- |
| 213 // Support functions. | 239 // Support functions. |
| 214 | 240 |
| 215 // Try to get function prototype of a function and puts the value in | 241 // Try to get function prototype of a function and puts the value in |
| 216 // the result register. Checks that the function really is a | 242 // the result register. Checks that the function really is a |
| 217 // function and jumps to the miss label if the fast checks fail. The | 243 // function and jumps to the miss label if the fast checks fail. The |
| 218 // function register will be untouched; the other registers may be | 244 // function register will be untouched; the other registers may be |
| 219 // clobbered. | 245 // clobbered. |
| 220 void TryGetFunctionPrototype(Register function, | 246 void TryGetFunctionPrototype(Register function, |
| 221 Register result, | 247 Register result, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 236 | 262 |
| 237 // Compare instance type in a map. map contains a valid map object whose | 263 // Compare instance type in a map. map contains a valid map object whose |
| 238 // object type should be compared with the given type. This both | 264 // object type should be compared with the given type. This both |
| 239 // sets the flags and leaves the object type in the type_reg register. It | 265 // sets the flags and leaves the object type in the type_reg register. It |
| 240 // leaves the heap object in the heap_object register unless the heap_object | 266 // leaves the heap object in the heap_object register unless the heap_object |
| 241 // register is the same register as type_reg. | 267 // register is the same register as type_reg. |
| 242 void CompareInstanceType(Register map, | 268 void CompareInstanceType(Register map, |
| 243 Register type_reg, | 269 Register type_reg, |
| 244 InstanceType type); | 270 InstanceType type); |
| 245 | 271 |
| 272 |
| 273 // Check if the map of an object is equal to a specified map and |
| 274 // branch to label if not. Skip the smi check if not required |
| 275 // (object is known to be a heap object) |
| 276 void CheckMap(Register obj, |
| 277 Register scratch, |
| 278 Handle<Map> map, |
| 279 Label* fail, |
| 280 bool is_heap_object); |
| 281 |
| 282 // Load and check the instance type of an object for being a string. |
| 283 // Loads the type into the second argument register. |
| 284 // Returns a condition that will be enabled if the object was a string. |
| 285 Condition IsObjectStringType(Register obj, |
| 286 Register type) { |
| 287 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 288 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset)); |
| 289 tst(type, Operand(kIsNotStringMask)); |
| 290 ASSERT_EQ(0, kStringTag); |
| 291 return eq; |
| 292 } |
| 293 |
| 294 |
| 246 inline void BranchOnSmi(Register value, Label* smi_label) { | 295 inline void BranchOnSmi(Register value, Label* smi_label) { |
| 247 tst(value, Operand(kSmiTagMask)); | 296 tst(value, Operand(kSmiTagMask)); |
| 248 b(eq, smi_label); | 297 b(eq, smi_label); |
| 249 } | 298 } |
| 250 | 299 |
| 251 inline void BranchOnNotSmi(Register value, Label* not_smi_label) { | 300 inline void BranchOnNotSmi(Register value, Label* not_smi_label) { |
| 252 tst(value, Operand(kSmiTagMask)); | 301 tst(value, Operand(kSmiTagMask)); |
| 253 b(ne, not_smi_label); | 302 b(ne, not_smi_label); |
| 254 } | 303 } |
| 255 | 304 |
| 256 // Generates code for reporting that an illegal operation has | 305 // Generates code for reporting that an illegal operation has |
| 257 // occurred. | 306 // occurred. |
| 258 void IllegalOperation(int num_arguments); | 307 void IllegalOperation(int num_arguments); |
| 259 | 308 |
| 309 // Get the number of least significant bits from a register |
| 310 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); |
| 311 |
| 260 // Uses VFP instructions to Convert a Smi to a double. | 312 // Uses VFP instructions to Convert a Smi to a double. |
| 261 void IntegerToDoubleConversionWithVFP3(Register inReg, | 313 void IntegerToDoubleConversionWithVFP3(Register inReg, |
| 262 Register outHighReg, | 314 Register outHighReg, |
| 263 Register outLowReg); | 315 Register outLowReg); |
| 264 | 316 |
| 265 | 317 |
| 266 // --------------------------------------------------------------------------- | 318 // --------------------------------------------------------------------------- |
| 267 // Runtime calls | 319 // Runtime calls |
| 268 | 320 |
| 269 // Call a code stub. | 321 // Call a code stub. |
| 270 void CallStub(CodeStub* stub, Condition cond = al); | 322 void CallStub(CodeStub* stub, Condition cond = al); |
| 271 | 323 |
| 324 // Call a code stub. |
| 325 void TailCallStub(CodeStub* stub, Condition cond = al); |
| 326 |
| 272 // Return from a code stub after popping its arguments. | 327 // Return from a code stub after popping its arguments. |
| 273 void StubReturn(int argc); | 328 void StubReturn(int argc); |
| 274 | 329 |
| 275 // Call a runtime routine. | 330 // Call a runtime routine. |
| 276 // Eventually this should be used for all C calls. | 331 // Eventually this should be used for all C calls. |
| 277 void CallRuntime(Runtime::Function* f, int num_arguments); | 332 void CallRuntime(Runtime::Function* f, int num_arguments); |
| 278 | 333 |
| 279 // Convenience function: Same as above, but takes the fid instead. | 334 // Convenience function: Same as above, but takes the fid instead. |
| 280 void CallRuntime(Runtime::FunctionId fid, int num_arguments); | 335 void CallRuntime(Runtime::FunctionId fid, int num_arguments); |
| 281 | 336 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 // Print a message to stdout and abort execution. | 386 // Print a message to stdout and abort execution. |
| 332 void Abort(const char* msg); | 387 void Abort(const char* msg); |
| 333 | 388 |
| 334 // Verify restrictions about code generated in stubs. | 389 // Verify restrictions about code generated in stubs. |
| 335 void set_generating_stub(bool value) { generating_stub_ = value; } | 390 void set_generating_stub(bool value) { generating_stub_ = value; } |
| 336 bool generating_stub() { return generating_stub_; } | 391 bool generating_stub() { return generating_stub_; } |
| 337 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 392 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } |
| 338 bool allow_stub_calls() { return allow_stub_calls_; } | 393 bool allow_stub_calls() { return allow_stub_calls_; } |
| 339 | 394 |
| 340 // --------------------------------------------------------------------------- | 395 // --------------------------------------------------------------------------- |
| 396 // Smi utilities |
| 397 |
| 398 // Jump if either of the registers contain a non-smi. |
| 399 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); |
| 400 // Jump if either of the registers contain a smi. |
| 401 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); |
| 402 |
| 403 // --------------------------------------------------------------------------- |
| 341 // String utilities | 404 // String utilities |
| 342 | 405 |
| 343 // Checks if both objects are sequential ASCII strings and jumps to label | 406 // Checks if both objects are sequential ASCII strings and jumps to label |
| 344 // if either is not. Assumes that neither object is a smi. | 407 // if either is not. Assumes that neither object is a smi. |
| 345 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, | 408 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1, |
| 346 Register object2, | 409 Register object2, |
| 347 Register scratch1, | 410 Register scratch1, |
| 348 Register scratch2, | 411 Register scratch2, |
| 349 Label *failure); | 412 Label *failure); |
| 350 | 413 |
| 351 // Checks if both objects are sequential ASCII strings and jumps to label | 414 // Checks if both objects are sequential ASCII strings and jumps to label |
| 352 // if either is not. | 415 // if either is not. |
| 353 void JumpIfNotBothSequentialAsciiStrings(Register first, | 416 void JumpIfNotBothSequentialAsciiStrings(Register first, |
| 354 Register second, | 417 Register second, |
| 355 Register scratch1, | 418 Register scratch1, |
| 356 Register scratch2, | 419 Register scratch2, |
| 357 Label* not_flat_ascii_strings); | 420 Label* not_flat_ascii_strings); |
| 358 | 421 |
| 359 private: | 422 private: |
| 360 List<Unresolved> unresolved_; | 423 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 361 bool generating_stub_; | 424 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); |
| 362 bool allow_stub_calls_; | |
| 363 Handle<Object> code_object_; // This handle will be patched with the code | |
| 364 // object on installation. | |
| 365 | 425 |
| 366 // Helper functions for generating invokes. | 426 // Helper functions for generating invokes. |
| 367 void InvokePrologue(const ParameterCount& expected, | 427 void InvokePrologue(const ParameterCount& expected, |
| 368 const ParameterCount& actual, | 428 const ParameterCount& actual, |
| 369 Handle<Code> code_constant, | 429 Handle<Code> code_constant, |
| 370 Register code_reg, | 430 Register code_reg, |
| 371 Label* done, | 431 Label* done, |
| 372 InvokeFlag flag); | 432 InvokeFlag flag); |
| 373 | 433 |
| 374 // Prepares for a call or jump to a builtin by doing two things: | 434 // Prepares for a call or jump to a builtin by doing two things: |
| 375 // 1. Emits code that fetches the builtin's function object from the context | 435 // 1. Emits code that fetches the builtin's function object from the context |
| 376 // at runtime, and puts it in the register rdi. | 436 // at runtime, and puts it in the register rdi. |
| 377 // 2. Fetches the builtin's code object, and returns it in a handle, at | 437 // 2. Fetches the builtin's code object, and returns it in a handle, at |
| 378 // compile time, so that later code can emit instructions to jump or call | 438 // compile time, so that later code can emit instructions to jump or call |
| 379 // the builtin directly. If the code object has not yet been created, it | 439 // the builtin directly. If the code object has not yet been created, it |
| 380 // returns the builtin code object for IllegalFunction, and sets the | 440 // returns the builtin code object for IllegalFunction, and sets the |
| 381 // output parameter "resolved" to false. Code that uses the return value | 441 // output parameter "resolved" to false. Code that uses the return value |
| 382 // should then add the address and the builtin name to the list of fixups | 442 // should then add the address and the builtin name to the list of fixups |
| 383 // called unresolved_, which is fixed up by the bootstrapper. | 443 // called unresolved_, which is fixed up by the bootstrapper. |
| 384 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved); | 444 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved); |
| 385 | 445 |
| 386 // Activation support. | 446 // Activation support. |
| 387 void EnterFrame(StackFrame::Type type); | 447 void EnterFrame(StackFrame::Type type); |
| 388 void LeaveFrame(StackFrame::Type type); | 448 void LeaveFrame(StackFrame::Type type); |
| 449 |
| 450 List<Unresolved> unresolved_; |
| 451 bool generating_stub_; |
| 452 bool allow_stub_calls_; |
| 453 // This handle will be patched with the code object on installation. |
| 454 Handle<Object> code_object_; |
| 389 }; | 455 }; |
| 390 | 456 |
| 391 | 457 |
| 392 #ifdef ENABLE_DEBUGGER_SUPPORT | 458 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 393 // The code patcher is used to patch (typically) small parts of code e.g. for | 459 // The code patcher is used to patch (typically) small parts of code e.g. for |
| 394 // debugging and other types of instrumentation. When using the code patcher | 460 // debugging and other types of instrumentation. When using the code patcher |
| 395 // the exact number of bytes specified must be emitted. It is not legal to emit | 461 // the exact number of bytes specified must be emitted. It is not legal to emit |
| 396 // relocation information. If any of these constraints are violated it causes | 462 // relocation information. If any of these constraints are violated it causes |
| 397 // an assertion to fail. | 463 // an assertion to fail. |
| 398 class CodePatcher { | 464 class CodePatcher { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 414 int instructions_; // Number of instructions of the expected patch size. | 480 int instructions_; // Number of instructions of the expected patch size. |
| 415 int size_; // Number of bytes of the expected patch size. | 481 int size_; // Number of bytes of the expected patch size. |
| 416 MacroAssembler masm_; // Macro assembler used to generate the code. | 482 MacroAssembler masm_; // Macro assembler used to generate the code. |
| 417 }; | 483 }; |
| 418 #endif // ENABLE_DEBUGGER_SUPPORT | 484 #endif // ENABLE_DEBUGGER_SUPPORT |
| 419 | 485 |
| 420 | 486 |
| 421 // ----------------------------------------------------------------------------- | 487 // ----------------------------------------------------------------------------- |
| 422 // Static helper functions. | 488 // Static helper functions. |
| 423 | 489 |
| 424 // Generate a MemOperand for loading a field from an object. | |
| 425 static inline MemOperand FieldMemOperand(Register object, int offset) { | |
| 426 return MemOperand(object, offset - kHeapObjectTag); | |
| 427 } | |
| 428 | |
| 429 | |
| 430 #ifdef GENERATED_CODE_COVERAGE | 490 #ifdef GENERATED_CODE_COVERAGE |
| 431 #define CODE_COVERAGE_STRINGIFY(x) #x | 491 #define CODE_COVERAGE_STRINGIFY(x) #x |
| 432 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) | 492 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) |
| 433 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) | 493 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) |
| 434 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> | 494 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> |
| 435 #else | 495 #else |
| 436 #define ACCESS_MASM(masm) masm-> | 496 #define ACCESS_MASM(masm) masm-> |
| 437 #endif | 497 #endif |
| 438 | 498 |
| 439 | 499 |
| 440 } } // namespace v8::internal | 500 } } // namespace v8::internal |
| 441 | 501 |
| 442 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ | 502 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ |
| OLD | NEW |