Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(223)

Delta Between Two Patch Sets: src/pkg/runtime/stack.c

Issue 12053043: code review 12053043: runtime: reimplement reflect.call to not use stack spli... (Closed)
Left Patch Set: Created 11 years, 8 months ago
Right Patch Set: diff -r 5cdc93018bcf https://khr%40golang.org@code.google.com/p/go/ Created 11 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/runtime.h ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 #include "runtime.h" 5 #include "runtime.h"
6 #include "arch_GOARCH.h" 6 #include "arch_GOARCH.h"
7 #include "malloc.h" 7 #include "malloc.h"
8 #include "stack.h" 8 #include "stack.h"
9 9
10 enum 10 enum
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 gp->stackguard = top->stackguard; 176 gp->stackguard = top->stackguard;
177 gp->stackguard0 = gp->stackguard; 177 gp->stackguard0 = gp->stackguard;
178 178
179 if(top->free != 0) 179 if(top->free != 0)
180 runtime·stackfree(old, top->free); 180 runtime·stackfree(old, top->free);
181 181
182 gp->status = oldstatus; 182 gp->status = oldstatus;
183 runtime·gogo(&gp->sched); 183 runtime·gogo(&gp->sched);
184 } 184 }
185 185
186 // Called from reflect·call or from runtime·morestack when a new 186 // Called from runtime·newstackcall or from runtime·morestack when a new
187 // stack segment is needed. Allocate a new stack big enough for 187 // stack segment is needed. Allocate a new stack big enough for
188 // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, 188 // m->moreframesize bytes, copy m->moreargsize bytes to the new frame,
189 // and then act as though runtime·lessstack called the function at 189 // and then act as though runtime·lessstack called the function at
190 // m->morepc. 190 // m->morepc.
191 void 191 void
192 runtime·newstack(void) 192 runtime·newstack(void)
193 { 193 {
194 int32 framesize, argsize, oldstatus; 194 int32 framesize, argsize, oldstatus;
195 Stktop *top; 195 Stktop *top;
196 byte *stk; 196 byte *stk;
197 uintptr sp; 197 uintptr sp;
198 uintptr *src, *dst, *dstend; 198 uintptr *src, *dst, *dstend;
199 G *gp; 199 G *gp;
200 Gobuf label; 200 Gobuf label;
201 » bool reflectcall; 201 » bool newstackcall;
202 uintptr free; 202 uintptr free;
203 203
204 if(m->morebuf.g != m->curg) { 204 if(m->morebuf.g != m->curg) {
205 runtime·printf("runtime: newstack called from g=%p\n" 205 runtime·printf("runtime: newstack called from g=%p\n"
206 "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n", 206 "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
207 m->morebuf.g, m, m->curg, m->g0, m->gsignal); 207 m->morebuf.g, m, m->curg, m->g0, m->gsignal);
208 runtime·throw("runtime: wrong goroutine in newstack"); 208 runtime·throw("runtime: wrong goroutine in newstack");
209 } 209 }
210 210
211 // gp->status is usually Grunning, but it could be Gsyscall if a stack s plit 211 // gp->status is usually Grunning, but it could be Gsyscall if a stack s plit
212 // happens during a function call inside entersyscall. 212 // happens during a function call inside entersyscall.
213 gp = m->curg; 213 gp = m->curg;
214 oldstatus = gp->status; 214 oldstatus = gp->status;
215 215
216 framesize = m->moreframesize; 216 framesize = m->moreframesize;
217 argsize = m->moreargsize; 217 argsize = m->moreargsize;
218 gp->status = Gwaiting; 218 gp->status = Gwaiting;
219 gp->waitreason = "stack split"; 219 gp->waitreason = "stack split";
220 » reflectcall = framesize==1; 220 » newstackcall = framesize==1;
221 » if(reflectcall) 221 » if(newstackcall)
222 framesize = 0; 222 framesize = 0;
223 223
224 » // For reflectcall the context already points to beginning of reflect·ca ll. 224 » // For newstackcall the context already points to beginning of runtime·n ewstackcall.
225 » if(!reflectcall) 225 » if(!newstackcall)
226 runtime·rewindmorestack(&gp->sched); 226 runtime·rewindmorestack(&gp->sched);
227 227
228 sp = gp->sched.sp; 228 sp = gp->sched.sp;
229 if(thechar == '6' || thechar == '8') { 229 if(thechar == '6' || thechar == '8') {
230 // The call to morestack cost a word. 230 // The call to morestack cost a word.
231 sp -= sizeof(uintptr); 231 sp -= sizeof(uintptr);
232 } 232 }
233 if(StackDebug || sp < gp->stackguard - StackGuard) { 233 if(StackDebug || sp < gp->stackguard - StackGuard) {
234 runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p stack=[%p, %p]\n" 234 runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p stack=[%p, %p]\n"
235 "\tmorebuf={pc:%p sp:%p lr:%p}\n" 235 "\tmorebuf={pc:%p sp:%p lr:%p}\n"
(...skipping 26 matching lines...) Expand all
262 // gp->preempt is set, so it will be preempted next time . 262 // gp->preempt is set, so it will be preempted next time .
263 gp->stackguard0 = gp->stackguard; 263 gp->stackguard0 = gp->stackguard;
264 gp->status = oldstatus; 264 gp->status = oldstatus;
265 runtime·gogo(&gp->sched); // never return 265 runtime·gogo(&gp->sched); // never return
266 } 266 }
267 // Act like goroutine called runtime.Gosched. 267 // Act like goroutine called runtime.Gosched.
268 gp->status = oldstatus; 268 gp->status = oldstatus;
269 runtime·gosched0(gp); // never return 269 runtime·gosched0(gp); // never return
270 } 270 }
271 271
272 » if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->st ackguard) { 272 » if(newstackcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->s tackguard) {
273 » » // special case: called from reflect.call (framesize==1) 273 » » // special case: called from runtime.newstackcall (framesize==1)
274 // to call code with an arbitrary argument size, 274 // to call code with an arbitrary argument size,
275 // and we have enough space on the current stack. 275 // and we have enough space on the current stack.
276 // the new Stktop* is necessary to unwind, but 276 // the new Stktop* is necessary to unwind, but
277 // we don't need to create a new segment. 277 // we don't need to create a new segment.
278 top = (Stktop*)(m->morebuf.sp - sizeof(*top)); 278 top = (Stktop*)(m->morebuf.sp - sizeof(*top));
279 stk = (byte*)gp->stackguard - StackGuard; 279 stk = (byte*)gp->stackguard - StackGuard;
280 free = 0; 280 free = 0;
281 } else { 281 } else {
282 // allocate new segment. 282 // allocate new segment.
283 framesize += argsize; 283 framesize += argsize;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 sp -= sizeof(void*); 327 sp -= sizeof(void*);
328 *(void**)sp = nil; 328 *(void**)sp = nil;
329 } 329 }
330 330
331 // Continue as if lessstack had just called m->morepc 331 // Continue as if lessstack had just called m->morepc
332 // (the PC that decided to grow the stack). 332 // (the PC that decided to grow the stack).
333 runtime·memclr((byte*)&label, sizeof label); 333 runtime·memclr((byte*)&label, sizeof label);
334 label.sp = sp; 334 label.sp = sp;
335 label.pc = (uintptr)runtime·lessstack; 335 label.pc = (uintptr)runtime·lessstack;
336 label.g = m->curg; 336 label.g = m->curg;
337 » if(reflectcall) 337 » if(newstackcall)
338 runtime·gostartcallfn(&label, (FuncVal*)m->cret); 338 runtime·gostartcallfn(&label, (FuncVal*)m->cret);
339 else { 339 else {
340 runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sch ed.ctxt); 340 runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sch ed.ctxt);
341 gp->sched.ctxt = nil; 341 gp->sched.ctxt = nil;
342 } 342 }
343 gp->status = oldstatus; 343 gp->status = oldstatus;
344 runtime·gogo(&label); 344 runtime·gogo(&label);
345 345
346 *(int32*)345 = 123; // never return 346 *(int32*)345 = 123; // never return
347 } 347 }
348 348
349 // adjust Gobuf as if it executed a call to fn 349 // adjust Gobuf as if it executed a call to fn
350 // and then did an immediate gosave. 350 // and then did an immediate gosave.
351 void 351 void
352 runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv) 352 runtime·gostartcallfn(Gobuf *gobuf, FuncVal *fv)
353 { 353 {
354 runtime·gostartcall(gobuf, fv->fn, fv); 354 runtime·gostartcall(gobuf, fv->fn, fv);
355 } 355 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b