~ubuntu-branches/ubuntu/trusty/libv8-3.14/trusty

« back to all changes in this revision

Viewing changes to src/ppc/debug-ppc.cc

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2014-02-12 10:26:54 UTC
  • Revision ID: package-import@ubuntu.com-20140212102654-mh2oalg31ifhjs0g
Tags: 3.14.5.8-5ubuntu1
* 0099_powerpc_support.patch: Pull in Andrew Low's powerpc port.
* debian/rules: Enable powerpc/ppc64/ppc64el for package builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
 
2
//
 
3
// Copyright IBM Corp. 2012, 2013. All rights reserved.
 
4
//
 
5
// Redistribution and use in source and binary forms, with or without
 
6
// modification, are permitted provided that the following conditions are
 
7
// met:
 
8
//
 
9
//     * Redistributions of source code must retain the above copyright
 
10
//       notice, this list of conditions and the following disclaimer.
 
11
//     * Redistributions in binary form must reproduce the above
 
12
//       copyright notice, this list of conditions and the following
 
13
//       disclaimer in the documentation and/or other materials provided
 
14
//       with the distribution.
 
15
//     * Neither the name of Google Inc. nor the names of its
 
16
//       contributors may be used to endorse or promote products derived
 
17
//       from this software without specific prior written permission.
 
18
//
 
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
 
 
31
#include "v8.h"
 
32
 
 
33
#if defined(V8_TARGET_ARCH_PPC)
 
34
 
 
35
#include "codegen.h"
 
36
#include "debug.h"
 
37
 
 
38
namespace v8 {
 
39
namespace internal {
 
40
 
 
41
#ifdef ENABLE_DEBUGGER_SUPPORT
 
42
bool BreakLocationIterator::IsDebugBreakAtReturn() {
 
43
  return Debug::IsDebugBreakAtReturn(rinfo());
 
44
}
 
45
 
 
46
 
 
47
void BreakLocationIterator::SetDebugBreakAtReturn() {
 
48
  // Patch the code changing the return from JS function sequence from
 
49
  //
 
50
  //   mr sp, fp
 
51
  //   lwz fp, 0(sp)
 
52
  //   lwz r0, 4(sp)
 
53
  //   mtlr r0
 
54
  //   addi sp, sp, <delta>
 
55
  //   blr
 
56
  //
 
57
  // to a call to the debug break return code.
 
58
  // this uses a FIXED_SEQUENCE to load a 32bit constant
 
59
  //
 
60
  //   lis r0, <address hi>
 
61
  //   ori r0, r0, <address lo>
 
62
  //   mtlr r0
 
63
  //   blrl
 
64
  //   bkpt
 
65
  //
 
66
  // The 64bit sequence is a bit longer
 
67
  //   lis r0, <address bits 63-48>
 
68
  //   ori r0, r0, <address bits 47-32>
 
69
  //   sldi r0, r0, 32
 
70
  //   oris r0, r0, <address bits 31-16>
 
71
  //   ori  r0, r0, <address bits 15-0>
 
72
  //   mtlr r0
 
73
  //   blrl
 
74
  //   bkpt
 
75
  //
 
76
  CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
 
77
// printf("SetDebugBreakAtReturn: pc=%08x\n", (unsigned int)rinfo()->pc());
 
78
  patcher.masm()->mov(v8::internal::r0,
 
79
    Operand(reinterpret_cast<intptr_t>(
 
80
      Isolate::Current()->debug()->debug_break_return()->entry())));
 
81
  patcher.masm()->mtlr(v8::internal::r0);
 
82
  patcher.masm()->bclr(BA, SetLK);
 
83
  patcher.masm()->bkpt(0);
 
84
}
 
85
 
 
86
 
 
87
// Restore the JS frame exit code.
 
88
void BreakLocationIterator::ClearDebugBreakAtReturn() {
 
89
  rinfo()->PatchCode(original_rinfo()->pc(),
 
90
                     Assembler::kJSReturnSequenceInstructions);
 
91
}
 
92
 
 
93
 
 
94
// A debug break in the frame exit code is identified by the JS frame exit code
 
95
// having been patched with a call instruction.
 
96
bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
 
97
  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
 
98
  return rinfo->IsPatchedReturnSequence();
 
99
}
 
100
 
 
101
 
 
102
bool BreakLocationIterator::IsDebugBreakAtSlot() {
 
103
  ASSERT(IsDebugBreakSlot());
 
104
  // Check whether the debug break slot instructions have been patched.
 
105
  return rinfo()->IsPatchedDebugBreakSlotSequence();
 
106
}
 
107
 
 
108
 
 
109
void BreakLocationIterator::SetDebugBreakAtSlot() {
 
110
  ASSERT(IsDebugBreakSlot());
 
111
  // Patch the code changing the debug break slot code from
 
112
  //
 
113
  //   ori r3, r3, 0
 
114
  //   ori r3, r3, 0
 
115
  //   ori r3, r3, 0
 
116
  //   ori r3, r3, 0
 
117
  //   ori r3, r3, 0
 
118
  //
 
119
  // to a call to the debug break code, using a FIXED_SEQUENCE.
 
120
  //
 
121
  //   lis r0, <address hi>
 
122
  //   ori r0, r0, <address lo>
 
123
  //   mtlr r0
 
124
  //   blrl
 
125
  //
 
126
  // The 64bit sequence is +3 instructions longer for the load
 
127
  //
 
128
  CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
 
129
// printf("SetDebugBreakAtSlot: pc=%08x\n", (unsigned int)rinfo()->pc());
 
130
  patcher.masm()->mov(v8::internal::r0,
 
131
            Operand(reinterpret_cast<intptr_t>(
 
132
                   Isolate::Current()->debug()->debug_break_slot()->entry())));
 
133
  patcher.masm()->mtlr(v8::internal::r0);
 
134
  patcher.masm()->bclr(BA, SetLK);
 
135
}
 
136
 
 
137
 
 
138
void BreakLocationIterator::ClearDebugBreakAtSlot() {
 
139
  ASSERT(IsDebugBreakSlot());
 
140
  rinfo()->PatchCode(original_rinfo()->pc(),
 
141
                     Assembler::kDebugBreakSlotInstructions);
 
142
}
 
143
 
 
144
const bool Debug::FramePaddingLayout::kIsSupported = false;
 
145
 
 
146
 
 
147
#define __ ACCESS_MASM(masm)
 
148
 
 
149
 
 
150
static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 
151
                                          RegList object_regs,
 
152
                                          RegList non_object_regs) {
 
153
  {
 
154
    FrameScope scope(masm, StackFrame::INTERNAL);
 
155
 
 
156
// printf("Generate_DebugBreakCallHelper\n");
 
157
    // Store the registers containing live values on the expression stack to
 
158
    // make sure that these are correctly updated during GC. Non object values
 
159
    // are stored as a smi causing it to be untouched by GC.
 
160
    ASSERT((object_regs & ~kJSCallerSaved) == 0);
 
161
    ASSERT((non_object_regs & ~kJSCallerSaved) == 0);
 
162
    ASSERT((object_regs & non_object_regs) == 0);
 
163
    if ((object_regs | non_object_regs) != 0) {
 
164
      for (int i = 0; i < kNumJSCallerSaved; i++) {
 
165
        int r = JSCallerSavedCode(i);
 
166
        Register reg = { r };
 
167
        if ((non_object_regs & (1 << r)) != 0) {
 
168
          if (FLAG_debug_code) {
 
169
            __ andis(r0, reg, Operand(0xc000));
 
170
            __ Assert(eq, "Unable to encode value as smi", cr0);
 
171
          }
 
172
          __ SmiTag(reg);
 
173
        }
 
174
      }
 
175
      __ MultiPush(object_regs | non_object_regs);
 
176
    }
 
177
 
 
178
#ifdef DEBUG
 
179
    __ RecordComment("// Calling from debug break to runtime - come in - over");
 
180
#endif
 
181
    __ mov(r3, Operand(0, RelocInfo::NONE));  // no arguments
 
182
    __ mov(r4, Operand(ExternalReference::debug_break(masm->isolate())));
 
183
 
 
184
    CEntryStub ceb(1);
 
185
    __ CallStub(&ceb);
 
186
 
 
187
    // Restore the register values from the expression stack.
 
188
    if ((object_regs | non_object_regs) != 0) {
 
189
      __ MultiPop(object_regs | non_object_regs);
 
190
      for (int i = 0; i < kNumJSCallerSaved; i++) {
 
191
        int r = JSCallerSavedCode(i);
 
192
        Register reg = { r };
 
193
        if ((non_object_regs & (1 << r)) != 0) {
 
194
          __ SmiUntag(reg);
 
195
        }
 
196
        if (FLAG_debug_code &&
 
197
            (((object_regs |non_object_regs) & (1 << r)) == 0)) {
 
198
          __ mov(reg, Operand(kDebugZapValue));
 
199
        }
 
200
      }
 
201
    }
 
202
 
 
203
    // Leave the internal frame.
 
204
  }
 
205
 
 
206
  // Now that the break point has been handled, resume normal execution by
 
207
  // jumping to the target address intended by the caller and that was
 
208
  // overwritten by the address of DebugBreakXXX.
 
209
  ExternalReference after_break_target =
 
210
      ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
 
211
  __ mov(ip, Operand(after_break_target));
 
212
  __ LoadP(ip, MemOperand(ip));
 
213
  __ Jump(ip);
 
214
}
 
215
 
 
216
 
 
217
void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
 
218
  // Calling convention for IC load (from ic-ppc.cc).
 
219
  // ----------- S t a t e -------------
 
220
  //  -- r5    : name
 
221
  //  -- lr    : return address
 
222
  //  -- r3    : receiver
 
223
  //  -- [sp]  : receiver
 
224
  // -----------------------------------
 
225
  // Registers r3 and r5 contain objects that need to be pushed on the
 
226
  // expression stack of the fake JS frame.
 
227
  Generate_DebugBreakCallHelper(masm, r3.bit() | r5.bit(), 0);
 
228
}
 
229
 
 
230
 
 
231
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
 
232
  // Calling convention for IC store (from ic-ppc.cc).
 
233
  // ----------- S t a t e -------------
 
234
  //  -- r3    : value
 
235
  //  -- r4    : receiver
 
236
  //  -- r5    : name
 
237
  //  -- lr    : return address
 
238
  // -----------------------------------
 
239
  // Registers r3, r4, and r5 contain objects that need to be pushed on the
 
240
  // expression stack of the fake JS frame.
 
241
  Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit() | r5.bit(), 0);
 
242
}
 
243
 
 
244
 
 
245
void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
 
246
  // ---------- S t a t e --------------
 
247
  //  -- lr     : return address
 
248
  //  -- r3     : key
 
249
  //  -- r4     : receiver
 
250
  Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit(), 0);
 
251
}
 
252
 
 
253
 
 
254
void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
 
255
  // ---------- S t a t e --------------
 
256
  //  -- r3     : value
 
257
  //  -- r4     : key
 
258
  //  -- r5     : receiver
 
259
  //  -- lr     : return address
 
260
  Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit() | r5.bit(), 0);
 
261
}
 
262
 
 
263
 
 
264
void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
 
265
  // Calling convention for IC call (from ic-ppc.cc)
 
266
  // ----------- S t a t e -------------
 
267
  //  -- r5     : name
 
268
  // -----------------------------------
 
269
  Generate_DebugBreakCallHelper(masm, r5.bit(), 0);
 
270
}
 
271
 
 
272
 
 
273
void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
 
274
  // In places other than IC call sites it is expected that r3 is TOS which
 
275
  // is an object - this is not generally the case so this should be used with
 
276
  // care.
 
277
  Generate_DebugBreakCallHelper(masm, r3.bit(), 0);
 
278
}
 
279
 
 
280
 
 
281
void Debug::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
 
282
  // Register state for CallFunctionStub (from code-stubs-ppc.cc).
 
283
  // ----------- S t a t e -------------
 
284
  //  -- r4 : function
 
285
  // -----------------------------------
 
286
  Generate_DebugBreakCallHelper(masm, r4.bit(), 0);
 
287
}
 
288
 
 
289
 
 
290
void Debug::GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm) {
 
291
  // Register state for CallFunctionStub (from code-stubs-ppc.cc).
 
292
  // ----------- S t a t e -------------
 
293
  //  -- r4 : function
 
294
  //  -- r5 : cache cell for call target
 
295
  // -----------------------------------
 
296
  Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit(), 0);
 
297
}
 
298
 
 
299
 
 
300
void Debug::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
 
301
  // Calling convention for CallConstructStub (from code-stubs-ppc.cc)
 
302
  // ----------- S t a t e -------------
 
303
  //  -- r3     : number of arguments (not smi)
 
304
  //  -- r4     : constructor function
 
305
  // -----------------------------------
 
306
  Generate_DebugBreakCallHelper(masm, r4.bit(), r3.bit());
 
307
}
 
308
 
 
309
 
 
310
void Debug::GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm) {
 
311
  // Calling convention for CallConstructStub (from code-stubs-ppc.cc)
 
312
  // ----------- S t a t e -------------
 
313
  //  -- r3     : number of arguments (not smi)
 
314
  //  -- r4     : constructor function
 
315
  //  -- r5     : cache cell for call target
 
316
  // -----------------------------------
 
317
  Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit(), r3.bit());
 
318
}
 
319
 
 
320
 
 
321
void Debug::GenerateSlot(MacroAssembler* masm) {
 
322
  // Generate enough nop's to make space for a call instruction. Avoid emitting
 
323
  // the trampoline pool in the debug break slot code.
 
324
  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
 
325
  Label check_codesize;
 
326
  __ bind(&check_codesize);
 
327
  __ RecordDebugBreakSlot();
 
328
  for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
 
329
    __ nop(MacroAssembler::DEBUG_BREAK_NOP);
 
330
  }
 
331
  ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
 
332
            masm->InstructionsGeneratedSince(&check_codesize));
 
333
}
 
334
 
 
335
 
 
336
void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
 
337
  // In the places where a debug break slot is inserted no registers can contain
 
338
  // object pointers.
 
339
  Generate_DebugBreakCallHelper(masm, 0, 0);
 
340
}
 
341
 
 
342
 
 
343
void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
 
344
  masm->Abort("LiveEdit frame dropping is not supported on ppc");
 
345
}
 
346
 
 
347
 
 
348
void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
 
349
  masm->Abort("LiveEdit frame dropping is not supported on ppc");
 
350
}
 
351
 
 
352
const bool Debug::kFrameDropperSupported = false;
 
353
 
 
354
#undef __
 
355
 
 
356
 
 
357
 
 
358
#endif  // ENABLE_DEBUGGER_SUPPORT
 
359
 
 
360
} }  // namespace v8::internal
 
361
 
 
362
#endif  // V8_TARGET_ARCH_PPC