The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / arm / lithium-codegen-arm.h @ f230a1cf

History | View | Annotate | Download (16.9 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#ifndef V8_ARM_LITHIUM_CODEGEN_ARM_H_
29
#define V8_ARM_LITHIUM_CODEGEN_ARM_H_
30

    
31
#include "arm/lithium-arm.h"
32

    
33
#include "arm/lithium-gap-resolver-arm.h"
34
#include "deoptimizer.h"
35
#include "lithium-codegen.h"
36
#include "safepoint-table.h"
37
#include "scopes.h"
38
#include "v8utils.h"
39

    
40
namespace v8 {
41
namespace internal {
42

    
43
// Forward declarations.
44
class LDeferredCode;
45
class SafepointGenerator;
46

    
47
class LCodeGen: public LCodeGenBase {
48
 public:
49
  LCodeGen(LChunk* chunk, MacroAssembler* assembler, CompilationInfo* info)
50
      : LCodeGenBase(chunk, assembler, info),
51
        deoptimizations_(4, info->zone()),
52
        deopt_jump_table_(4, info->zone()),
53
        deoptimization_literals_(8, info->zone()),
54
        inlined_function_count_(0),
55
        scope_(info->scope()),
56
        translations_(info->zone()),
57
        deferred_(8, info->zone()),
58
        osr_pc_offset_(-1),
59
        frame_is_built_(false),
60
        safepoints_(info->zone()),
61
        resolver_(this),
62
        expected_safepoint_kind_(Safepoint::kSimple) {
63
    PopulateDeoptimizationLiteralsWithInlinedFunctions();
64
  }
65

    
66

    
67
  int LookupDestination(int block_id) const {
68
    return chunk()->LookupDestination(block_id);
69
  }
70

    
71
  bool IsNextEmittedBlock(int block_id) const {
72
    return LookupDestination(block_id) == GetNextEmittedBlock();
73
  }
74

    
75
  bool NeedsEagerFrame() const {
76
    return GetStackSlotCount() > 0 ||
77
        info()->is_non_deferred_calling() ||
78
        !info()->IsStub() ||
79
        info()->requires_frame();
80
  }
81
  bool NeedsDeferredFrame() const {
82
    return !NeedsEagerFrame() && info()->is_deferred_calling();
83
  }
84

    
85
  LinkRegisterStatus GetLinkRegisterState() const {
86
    return frame_is_built_ ? kLRHasBeenSaved : kLRHasNotBeenSaved;
87
  }
88

    
89
  // Support for converting LOperands to assembler types.
90
  // LOperand must be a register.
91
  Register ToRegister(LOperand* op) const;
92

    
93
  // LOperand is loaded into scratch, unless already a register.
94
  Register EmitLoadRegister(LOperand* op, Register scratch);
95

    
96
  // LOperand must be a double register.
97
  DwVfpRegister ToDoubleRegister(LOperand* op) const;
98

    
99
  // LOperand is loaded into dbl_scratch, unless already a double register.
100
  DwVfpRegister EmitLoadDoubleRegister(LOperand* op,
101
                                       SwVfpRegister flt_scratch,
102
                                       DwVfpRegister dbl_scratch);
103
  int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const;
104
  int32_t ToInteger32(LConstantOperand* op) const;
105
  Smi* ToSmi(LConstantOperand* op) const;
106
  double ToDouble(LConstantOperand* op) const;
107
  Operand ToOperand(LOperand* op);
108
  MemOperand ToMemOperand(LOperand* op) const;
109
  // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
110
  MemOperand ToHighMemOperand(LOperand* op) const;
111

    
112
  bool IsInteger32(LConstantOperand* op) const;
113
  bool IsSmi(LConstantOperand* op) const;
114
  Handle<Object> ToHandle(LConstantOperand* op) const;
115

    
116
  // Try to generate code for the entire chunk, but it may fail if the
117
  // chunk contains constructs we cannot handle. Returns true if the
118
  // code generation attempt succeeded.
119
  bool GenerateCode();
120

    
121
  // Finish the code by setting stack height, safepoint, and bailout
122
  // information on it.
123
  void FinishCode(Handle<Code> code);
124

    
125
  // Deferred code support.
126
  void DoDeferredNumberTagD(LNumberTagD* instr);
127

    
128
  enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
129
  void DoDeferredNumberTagI(LInstruction* instr,
130
                            LOperand* value,
131
                            IntegerSignedness signedness);
132

    
133
  void DoDeferredTaggedToI(LTaggedToI* instr);
134
  void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
135
  void DoDeferredStackCheck(LStackCheck* instr);
136
  void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
137
  void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
138
  void DoDeferredAllocate(LAllocate* instr);
139
  void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
140
                                       Label* map_check);
141
  void DoDeferredInstanceMigration(LCheckMaps* instr, Register object);
142

    
143
  // Parallel move support.
144
  void DoParallelMove(LParallelMove* move);
145
  void DoGap(LGap* instr);
146

    
147
  MemOperand PrepareKeyedOperand(Register key,
148
                                 Register base,
149
                                 bool key_is_constant,
150
                                 int constant_key,
151
                                 int element_size,
152
                                 int shift_size,
153
                                 int additional_index,
154
                                 int additional_offset);
155

    
156
  // Emit frame translation commands for an environment.
157
  void WriteTranslation(LEnvironment* environment, Translation* translation);
158

    
159
  // Declare methods that deal with the individual node types.
160
#define DECLARE_DO(type) void Do##type(L##type* node);
161
  LITHIUM_CONCRETE_INSTRUCTION_LIST(DECLARE_DO)
162
#undef DECLARE_DO
163

    
164
 private:
165
  StrictModeFlag strict_mode_flag() const {
166
    return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
167
  }
168

    
169
  Scope* scope() const { return scope_; }
170

    
171
  Register scratch0() { return r9; }
172
  LowDwVfpRegister double_scratch0() { return kScratchDoubleReg; }
173

    
174
  LInstruction* GetNextInstruction();
175

    
176
  void EmitClassOfTest(Label* if_true,
177
                       Label* if_false,
178
                       Handle<String> class_name,
179
                       Register input,
180
                       Register temporary,
181
                       Register temporary2);
182

    
183
  int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
184

    
185
  void Abort(BailoutReason reason);
186

    
187
  void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
188

    
189
  // Code generation passes.  Returns true if code generation should
190
  // continue.
191
  bool GeneratePrologue();
192
  bool GenerateDeferredCode();
193
  bool GenerateDeoptJumpTable();
194
  bool GenerateSafepointTable();
195

    
196
  // Generates the custom OSR entrypoint and sets the osr_pc_offset.
197
  void GenerateOsrPrologue();
198

    
199
  enum SafepointMode {
200
    RECORD_SIMPLE_SAFEPOINT,
201
    RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS
202
  };
203

    
204
  void CallCode(
205
      Handle<Code> code,
206
      RelocInfo::Mode mode,
207
      LInstruction* instr,
208
      TargetAddressStorageMode storage_mode = CAN_INLINE_TARGET_ADDRESS);
209

    
210
  void CallCodeGeneric(
211
      Handle<Code> code,
212
      RelocInfo::Mode mode,
213
      LInstruction* instr,
214
      SafepointMode safepoint_mode,
215
      TargetAddressStorageMode storage_mode = CAN_INLINE_TARGET_ADDRESS);
216

    
217
  void CallRuntime(const Runtime::Function* function,
218
                   int num_arguments,
219
                   LInstruction* instr,
220
                   SaveFPRegsMode save_doubles = kDontSaveFPRegs);
221

    
222
  void CallRuntime(Runtime::FunctionId id,
223
                   int num_arguments,
224
                   LInstruction* instr) {
225
    const Runtime::Function* function = Runtime::FunctionForId(id);
226
    CallRuntime(function, num_arguments, instr);
227
  }
228

    
229
  void LoadContextFromDeferred(LOperand* context);
230
  void CallRuntimeFromDeferred(Runtime::FunctionId id,
231
                               int argc,
232
                               LInstruction* instr,
233
                               LOperand* context);
234

    
235
  enum R1State {
236
    R1_UNINITIALIZED,
237
    R1_CONTAINS_TARGET
238
  };
239

    
240
  // Generate a direct call to a known function.  Expects the function
241
  // to be in r1.
242
  void CallKnownFunction(Handle<JSFunction> function,
243
                         int formal_parameter_count,
244
                         int arity,
245
                         LInstruction* instr,
246
                         CallKind call_kind,
247
                         R1State r1_state);
248

    
249
  void RecordSafepointWithLazyDeopt(LInstruction* instr,
250
                                    SafepointMode safepoint_mode);
251

    
252
  void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
253
                                            Safepoint::DeoptMode mode);
254
  void DeoptimizeIf(Condition condition,
255
                    LEnvironment* environment,
256
                    Deoptimizer::BailoutType bailout_type);
257
  void DeoptimizeIf(Condition condition, LEnvironment* environment);
258
  void ApplyCheckIf(Condition condition, LBoundsCheck* check);
259

    
260
  void AddToTranslation(LEnvironment* environment,
261
                        Translation* translation,
262
                        LOperand* op,
263
                        bool is_tagged,
264
                        bool is_uint32,
265
                        int* object_index_pointer,
266
                        int* dematerialized_index_pointer);
267
  void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
268
  void PopulateDeoptimizationData(Handle<Code> code);
269
  int DefineDeoptimizationLiteral(Handle<Object> literal);
270

    
271
  void PopulateDeoptimizationLiteralsWithInlinedFunctions();
272

    
273
  Register ToRegister(int index) const;
274
  DwVfpRegister ToDoubleRegister(int index) const;
275

    
276
  void EmitIntegerMathAbs(LMathAbs* instr);
277

    
278
  // Support for recording safepoint and position information.
279
  void RecordSafepoint(LPointerMap* pointers,
280
                       Safepoint::Kind kind,
281
                       int arguments,
282
                       Safepoint::DeoptMode mode);
283
  void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
284
  void RecordSafepoint(Safepoint::DeoptMode mode);
285
  void RecordSafepointWithRegisters(LPointerMap* pointers,
286
                                    int arguments,
287
                                    Safepoint::DeoptMode mode);
288
  void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
289
                                              int arguments,
290
                                              Safepoint::DeoptMode mode);
291

    
292
  void RecordAndWritePosition(int position) V8_OVERRIDE;
293

    
294
  static Condition TokenToCondition(Token::Value op, bool is_unsigned);
295
  void EmitGoto(int block);
296
  template<class InstrType>
297
  void EmitBranch(InstrType instr, Condition condition);
298
  template<class InstrType>
299
  void EmitFalseBranch(InstrType instr, Condition condition);
300
  void EmitNumberUntagD(Register input,
301
                        DwVfpRegister result,
302
                        bool allow_undefined_as_nan,
303
                        bool deoptimize_on_minus_zero,
304
                        LEnvironment* env,
305
                        NumberUntagDMode mode);
306

    
307
  // Emits optimized code for typeof x == "y".  Modifies input register.
308
  // Returns the condition on which a final split to
309
  // true and false label should be made, to optimize fallthrough.
310
  Condition EmitTypeofIs(Label* true_label,
311
                         Label* false_label,
312
                         Register input,
313
                         Handle<String> type_name);
314

    
315
  // Emits optimized code for %_IsObject(x).  Preserves input register.
316
  // Returns the condition on which a final split to
317
  // true and false label should be made, to optimize fallthrough.
318
  Condition EmitIsObject(Register input,
319
                         Register temp1,
320
                         Label* is_not_object,
321
                         Label* is_object);
322

    
323
  // Emits optimized code for %_IsString(x).  Preserves input register.
324
  // Returns the condition on which a final split to
325
  // true and false label should be made, to optimize fallthrough.
326
  Condition EmitIsString(Register input,
327
                         Register temp1,
328
                         Label* is_not_string,
329
                         SmiCheck check_needed);
330

    
331
  // Emits optimized code for %_IsConstructCall().
332
  // Caller should branch on equal condition.
333
  void EmitIsConstructCall(Register temp1, Register temp2);
334

    
335
  // Emits optimized code to deep-copy the contents of statically known
336
  // object graphs (e.g. object literal boilerplate).
337
  void EmitDeepCopy(Handle<JSObject> object,
338
                    Register result,
339
                    Register source,
340
                    int* offset,
341
                    AllocationSiteMode mode);
342

    
343
  // Emit optimized code for integer division.
344
  // Inputs are signed.
345
  // All registers are clobbered.
346
  // If 'remainder' is no_reg, it is not computed.
347
  void EmitSignedIntegerDivisionByConstant(Register result,
348
                                           Register dividend,
349
                                           int32_t divisor,
350
                                           Register remainder,
351
                                           Register scratch,
352
                                           LEnvironment* environment);
353

    
354
  void EnsureSpaceForLazyDeopt(int space_needed) V8_OVERRIDE;
355
  void DoLoadKeyedExternalArray(LLoadKeyed* instr);
356
  void DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr);
357
  void DoLoadKeyedFixedArray(LLoadKeyed* instr);
358
  void DoStoreKeyedExternalArray(LStoreKeyed* instr);
359
  void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr);
360
  void DoStoreKeyedFixedArray(LStoreKeyed* instr);
361

    
362
  ZoneList<LEnvironment*> deoptimizations_;
363
  ZoneList<Deoptimizer::JumpTableEntry> deopt_jump_table_;
364
  ZoneList<Handle<Object> > deoptimization_literals_;
365
  int inlined_function_count_;
366
  Scope* const scope_;
367
  TranslationBuffer translations_;
368
  ZoneList<LDeferredCode*> deferred_;
369
  int osr_pc_offset_;
370
  bool frame_is_built_;
371

    
372
  // Builder that keeps track of safepoints in the code. The table
373
  // itself is emitted at the end of the generated code.
374
  SafepointTableBuilder safepoints_;
375

    
376
  // Compiler from a set of parallel moves to a sequential list of moves.
377
  LGapResolver resolver_;
378

    
379
  Safepoint::Kind expected_safepoint_kind_;
380

    
381
  class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED {
382
   public:
383
    PushSafepointRegistersScope(LCodeGen* codegen,
384
                                Safepoint::Kind kind)
385
        : codegen_(codegen) {
386
      ASSERT(codegen_->info()->is_calling());
387
      ASSERT(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
388
      codegen_->expected_safepoint_kind_ = kind;
389

    
390
      switch (codegen_->expected_safepoint_kind_) {
391
        case Safepoint::kWithRegisters:
392
          codegen_->masm_->PushSafepointRegisters();
393
          break;
394
        case Safepoint::kWithRegistersAndDoubles:
395
          codegen_->masm_->PushSafepointRegistersAndDoubles();
396
          break;
397
        default:
398
          UNREACHABLE();
399
      }
400
    }
401

    
402
    ~PushSafepointRegistersScope() {
403
      Safepoint::Kind kind = codegen_->expected_safepoint_kind_;
404
      ASSERT((kind & Safepoint::kWithRegisters) != 0);
405
      switch (kind) {
406
        case Safepoint::kWithRegisters:
407
          codegen_->masm_->PopSafepointRegisters();
408
          break;
409
        case Safepoint::kWithRegistersAndDoubles:
410
          codegen_->masm_->PopSafepointRegistersAndDoubles();
411
          break;
412
        default:
413
          UNREACHABLE();
414
      }
415
      codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
416
    }
417

    
418
   private:
419
    LCodeGen* codegen_;
420
  };
421

    
422
  friend class LDeferredCode;
423
  friend class LEnvironment;
424
  friend class SafepointGenerator;
425
  DISALLOW_COPY_AND_ASSIGN(LCodeGen);
426
};
427

    
428

    
429
class LDeferredCode : public ZoneObject {
430
 public:
431
  explicit LDeferredCode(LCodeGen* codegen)
432
      : codegen_(codegen),
433
        external_exit_(NULL),
434
        instruction_index_(codegen->current_instruction_) {
435
    codegen->AddDeferredCode(this);
436
  }
437

    
438
  virtual ~LDeferredCode() {}
439
  virtual void Generate() = 0;
440
  virtual LInstruction* instr() = 0;
441

    
442
  void SetExit(Label* exit) { external_exit_ = exit; }
443
  Label* entry() { return &entry_; }
444
  Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
445
  int instruction_index() const { return instruction_index_; }
446

    
447
 protected:
448
  LCodeGen* codegen() const { return codegen_; }
449
  MacroAssembler* masm() const { return codegen_->masm(); }
450

    
451
 private:
452
  LCodeGen* codegen_;
453
  Label entry_;
454
  Label exit_;
455
  Label* external_exit_;
456
  int instruction_index_;
457
};
458

    
459
} }  // namespace v8::internal
460

    
461
#endif  // V8_ARM_LITHIUM_CODEGEN_ARM_H_