00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029
00030 #include "v8.h"
00031
00032 #include "scopeinfo.h"
00033 #include "scopes.h"
00034
00035 namespace v8 { namespace internal {
00036
00037
00038 static int CompareLocal(Variable* const* v, Variable* const* w) {
00039 Slot* s = (*v)->slot();
00040 Slot* t = (*w)->slot();
00041
00042
00043 int x = (s != NULL ? s->index() : 0);
00044 int y = (t != NULL ? t->index() : 0);
00045
00046 return x - y;
00047 }
00048
00049
00050 template<class Allocator>
00051 ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
00052 : function_name_(Factory::empty_symbol()),
00053 supports_eval_(scope->SupportsEval()),
00054 parameters_(scope->num_parameters()),
00055 stack_slots_(scope->num_stack_slots()),
00056 context_slots_(scope->num_heap_slots()),
00057 context_modes_(scope->num_heap_slots()) {
00058
00059 for (int i = 0; i < scope->num_parameters(); i++) {
00060 ASSERT(parameters_.length() == i);
00061 parameters_.Add(scope->parameter(i)->name());
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 List<Variable*, Allocator> locals(32);
00077 ASSERT(locals.is_empty());
00078 scope->CollectUsedVariables(&locals);
00079 locals.Sort(&CompareLocal);
00080
00081 List<Variable*, Allocator> heap_locals(locals.length());
00082 for (int i = 0; i < locals.length(); i++) {
00083 Variable* var = locals[i];
00084 if (var->var_uses()->is_used()) {
00085 Slot* slot = var->slot();
00086 if (slot != NULL) {
00087 switch (slot->type()) {
00088 case Slot::PARAMETER:
00089
00090 break;
00091
00092 case Slot::LOCAL:
00093 ASSERT(stack_slots_.length() == slot->index());
00094 stack_slots_.Add(var->name());
00095 break;
00096
00097 case Slot::CONTEXT:
00098 heap_locals.Add(var);
00099 break;
00100
00101 case Slot::LOOKUP:
00102 case Slot::GLOBAL:
00103
00104 UNREACHABLE();
00105 break;
00106 }
00107 }
00108 }
00109 }
00110
00111
00112 if (scope->num_heap_slots() > 0) {
00113
00114 for (int i = 0; i < heap_locals.length(); i++) {
00115 ASSERT(heap_locals[i]->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
00116 context_slots_.length());
00117 ASSERT(heap_locals[i]->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
00118 context_modes_.length());
00119 context_slots_.Add(heap_locals[i]->name());
00120 context_modes_.Add(heap_locals[i]->mode());
00121 }
00122
00123 } else {
00124 ASSERT(heap_locals.length() == 0);
00125 }
00126
00127
00128
00129
00130 if (scope->is_function_scope()) {
00131 Variable* var = scope->function();
00132 if (var != NULL &&
00133 var->var_uses()->is_used() &&
00134 var->slot()->type() == Slot::CONTEXT) {
00135 function_name_ = var->name();
00136
00137
00138
00139
00140 ASSERT(var->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
00141 context_slots_.length());
00142 ASSERT(var->slot()->index() - Context::MIN_CONTEXT_SLOTS ==
00143 context_modes_.length());
00144 context_slots_.Add(Factory::empty_symbol());
00145 context_modes_.Add(Variable::INTERNAL);
00146 }
00147 }
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 static inline Object** ReadInt(Object** p, int* x) {
00191 *x = (reinterpret_cast<Smi*>(*p++))->value();
00192 return p;
00193 }
00194
00195
00196 static inline Object** ReadBool(Object** p, bool* x) {
00197 *x = (reinterpret_cast<Smi*>(*p++))->value() != 0;
00198 return p;
00199 }
00200
00201
00202 static inline Object** ReadSymbol(Object** p, Handle<String>* s) {
00203 *s = Handle<String>(reinterpret_cast<String*>(*p++));
00204 return p;
00205 }
00206
00207
00208 static inline Object** ReadSentinel(Object** p) {
00209 ASSERT(*p == NULL);
00210 return p + 1;
00211 }
00212
00213
00214 template <class Allocator>
00215 static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
00216 ASSERT(list->is_empty());
00217 int n;
00218 p = ReadInt(p, &n);
00219 while (n-- > 0) {
00220 Handle<String> s;
00221 p = ReadSymbol(p, &s);
00222 list->Add(s);
00223 }
00224 return ReadSentinel(p);
00225 }
00226
00227
00228 template <class Allocator>
00229 static Object** ReadList(Object** p,
00230 List<Handle<String>, Allocator>* list,
00231 List<Variable::Mode, Allocator>* modes) {
00232 ASSERT(list->is_empty());
00233 int n;
00234 p = ReadInt(p, &n);
00235 while (n-- > 0) {
00236 Handle<String> s;
00237 int m;
00238 p = ReadSymbol(p, &s);
00239 p = ReadInt(p, &m);
00240 list->Add(s);
00241 modes->Add(static_cast<Variable::Mode>(m));
00242 }
00243 return ReadSentinel(p);
00244 }
00245
00246
00247 template<class Allocator>
00248 ScopeInfo<Allocator>::ScopeInfo(Code* code)
00249 : function_name_(Factory::empty_symbol()),
00250 supports_eval_(false),
00251 parameters_(4),
00252 stack_slots_(8),
00253 context_slots_(8),
00254 context_modes_(8) {
00255 if (code == NULL || code->sinfo_size() == 0) return;
00256
00257 Object** p0 = &Memory::Object_at(code->sinfo_start());
00258 Object** p = p0;
00259 p = ReadSymbol(p, &function_name_);
00260 p = ReadBool(p, &supports_eval_);
00261 p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
00262 p = ReadList<Allocator>(p, ¶meters_);
00263 p = ReadList<Allocator>(p, &stack_slots_);
00264 ASSERT((p - p0) * kPointerSize == code->sinfo_size());
00265 }
00266
00267
00268 static inline Object** WriteInt(Object** p, int x) {
00269 *p++ = Smi::FromInt(x);
00270 return p;
00271 }
00272
00273
00274 static inline Object** WriteSymbol(Object** p, Handle<String> s) {
00275 *p++ = *s;
00276 return p;
00277 }
00278
00279
00280 static inline Object** WriteSentinel(Object** p) {
00281 *p++ = NULL;
00282 return p;
00283 }
00284
00285
00286 template <class Allocator>
00287 static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
00288 const int n = list->length();
00289 p = WriteInt(p, n);
00290 for (int i = 0; i < n; i++) {
00291 p = WriteSymbol(p, list->at(i));
00292 }
00293 return WriteSentinel(p);
00294 }
00295
00296
00297 template <class Allocator>
00298 static Object** WriteList(Object** p,
00299 List<Handle<String>, Allocator>* list,
00300 List<Variable::Mode, Allocator>* modes) {
00301 const int n = list->length();
00302 p = WriteInt(p, n);
00303 for (int i = 0; i < n; i++) {
00304 p = WriteSymbol(p, list->at(i));
00305 p = WriteInt(p, modes->at(i));
00306 }
00307 return WriteSentinel(p);
00308 }
00309
00310
00311 template<class Allocator>
00312 int ScopeInfo<Allocator>::Serialize(Code* code) {
00313
00314 const int extra_slots = 1 + 1 + 2 * 3;
00315 int size = (extra_slots +
00316 context_slots_.length() * 2 +
00317 parameters_.length() +
00318 stack_slots_.length()) * kPointerSize;
00319
00320 if (code != NULL) {
00321 CHECK(code->sinfo_size() == size);
00322 Object** p0 = &Memory::Object_at(code->sinfo_start());
00323 Object** p = p0;
00324 p = WriteSymbol(p, function_name_);
00325 p = WriteInt(p, supports_eval_);
00326 p = WriteList(p, &context_slots_, &context_modes_);
00327 p = WriteList(p, ¶meters_);
00328 p = WriteList(p, &stack_slots_);
00329 ASSERT((p - p0) * kPointerSize == size);
00330 }
00331
00332 return size;
00333 }
00334
00335
00336 template<class Allocator>
00337 void ScopeInfo<Allocator>::IterateScopeInfo(Code* code, ObjectVisitor* v) {
00338 Object** start = &Memory::Object_at(code->sinfo_start());
00339 Object** end = &Memory::Object_at(code->sinfo_start() + code->sinfo_size());
00340 v->VisitPointers(start, end);
00341 }
00342
00343
00344 static Object** ContextEntriesAddr(Code* code) {
00345 ASSERT(code->sinfo_size() > 0);
00346
00347 return &Memory::Object_at(code->sinfo_start()) + 2;
00348 }
00349
00350
00351 static Object** ParameterEntriesAddr(Code* code) {
00352 ASSERT(code->sinfo_size() > 0);
00353 Object** p = ContextEntriesAddr(code);
00354 int n;
00355 p = ReadInt(p, &n);
00356 return p + n*2 + 1;
00357 }
00358
00359
00360 static Object** StackSlotEntriesAddr(Code* code) {
00361 ASSERT(code->sinfo_size() > 0);
00362 Object** p = ParameterEntriesAddr(code);
00363 int n;
00364 p = ReadInt(p, &n);
00365 return p + n + 1;
00366 }
00367
00368
00369 template<class Allocator>
00370 bool ScopeInfo<Allocator>::SupportsEval(Code* code) {
00371 bool result = false;
00372 if (code->sinfo_size() > 0) {
00373 ReadBool(&Memory::Object_at(code->sinfo_start()) + 1, &result);
00374 }
00375 #ifdef DEBUG
00376 { ScopeInfo info(code);
00377 ASSERT(result == info.supports_eval_);
00378 }
00379 #endif
00380 return result;
00381 }
00382
00383
00384 template<class Allocator>
00385 int ScopeInfo<Allocator>::NumberOfStackSlots(Code* code) {
00386 if (code->sinfo_size() > 0) {
00387 Object** p = StackSlotEntriesAddr(code);
00388 int n;
00389 ReadInt(p, &n);
00390 return n;
00391 }
00392 return 0;
00393 }
00394
00395
00396 template<class Allocator>
00397 int ScopeInfo<Allocator>::NumberOfContextSlots(Code* code) {
00398 if (code->sinfo_size() > 0) {
00399 Object** p = ContextEntriesAddr(code);
00400 int n;
00401 ReadInt(p, &n);
00402 return n + Context::MIN_CONTEXT_SLOTS;
00403 }
00404 return 0;
00405 }
00406
00407
00408 template<class Allocator>
00409 int ScopeInfo<Allocator>::StackSlotIndex(Code* code, String* name) {
00410 ASSERT(name->IsSymbol());
00411 if (code->sinfo_size() > 0) {
00412
00413 ASSERT(NumberOfStackSlots(code) > 0 ||
00414 *(StackSlotEntriesAddr(code) + 1) == NULL);
00415
00416 Object** p0 = StackSlotEntriesAddr(code) + 1;
00417 Object** p = p0;
00418 while (*p != NULL) {
00419 if (*p == name) return p - p0;
00420 p++;
00421 }
00422 }
00423 return -1;
00424 }
00425
00426
00427 template<class Allocator>
00428 int ScopeInfo<Allocator>::ContextSlotIndex(Code* code,
00429 String* name,
00430 Variable::Mode* mode) {
00431 ASSERT(name->IsSymbol());
00432 if (code->sinfo_size() > 0) {
00433
00434 ASSERT(NumberOfContextSlots(code) >= Context::MIN_CONTEXT_SLOTS ||
00435 *(ContextEntriesAddr(code) + 1) == NULL);
00436
00437 Object** p0 = ContextEntriesAddr(code) + 1;
00438 Object** p = p0;
00439
00440 while (*p != NULL) {
00441 if (*p == name) {
00442 ASSERT(((p - p0) & 1) == 0);
00443 if (mode != NULL) {
00444 ReadInt(p + 1, reinterpret_cast<int*>(mode));
00445 }
00446 return ((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
00447 }
00448 p += 2;
00449 }
00450 }
00451 return -1;
00452 }
00453
00454
00455 template<class Allocator>
00456 int ScopeInfo<Allocator>::ParameterIndex(Code* code, String* name) {
00457 ASSERT(name->IsSymbol());
00458 if (code->sinfo_size() > 0) {
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 Object** p = ParameterEntriesAddr(code);
00470 int n;
00471 Object** p0 = ReadInt(p, &n);
00472 p = p0 + n;
00473 while (p > p0) {
00474 p--;
00475 if (*p == name) return p - p0;
00476 }
00477 }
00478 return -1;
00479 }
00480
00481
00482 template<class Allocator>
00483 int ScopeInfo<Allocator>::FunctionContextSlotIndex(Code* code, String* name) {
00484 ASSERT(name->IsSymbol());
00485 if (code->sinfo_size() > 0) {
00486 Object** p = &Memory::Object_at(code->sinfo_start());
00487 if (*p == name) {
00488 p = ContextEntriesAddr(code);
00489 int n;
00490 ReadInt(p, &n);
00491 ASSERT(n != 0);
00492
00493 return n + Context::MIN_CONTEXT_SLOTS - 1;
00494 }
00495 }
00496 return -1;
00497 }
00498
00499
00500 template<class Allocator>
00501 Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
00502
00503
00504
00505
00506 if (i < number_of_stack_slots()) {
00507 return stack_slot_name(i);
00508 } else {
00509 return context_slot_name(i - number_of_stack_slots() +
00510 Context::MIN_CONTEXT_SLOTS);
00511 }
00512 }
00513
00514
00515 template<class Allocator>
00516 int ScopeInfo<Allocator>::NumberOfLocals() const {
00517 int number_of_locals = number_of_stack_slots();
00518 if (number_of_context_slots() > 0) {
00519 ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
00520 number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
00521 }
00522 return number_of_locals;
00523 }
00524
00525
00526 #ifdef DEBUG
00527 template <class Allocator>
00528 static void PrintList(const char* list_name,
00529 int nof_internal_slots,
00530 List<Handle<String>, Allocator>& list) {
00531 if (list.length() > 0) {
00532 PrintF("\n // %s\n", list_name);
00533 if (nof_internal_slots > 0) {
00534 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
00535 }
00536 for (int i = 0; i < list.length(); i++) {
00537 PrintF(" %2d ", i + nof_internal_slots);
00538 list[i]->ShortPrint();
00539 PrintF("\n");
00540 }
00541 }
00542 }
00543
00544
00545 template<class Allocator>
00546 void ScopeInfo<Allocator>::Print() {
00547 PrintF("ScopeInfo ");
00548 if (function_name_->length() > 0)
00549 function_name_->ShortPrint();
00550 else
00551 PrintF("/* no function name */");
00552 PrintF("{");
00553
00554 if (supports_eval_)
00555 PrintF("\n // supports eval\n");
00556
00557 PrintList<Allocator>("parameters", 0, parameters_);
00558 PrintList<Allocator>("stack slots", 0, stack_slots_);
00559 PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS,
00560 context_slots_);
00561
00562 PrintF("}\n");
00563 }
00564 #endif // DEBUG
00565
00566
00567
00568 template class ScopeInfo<FreeStoreAllocationPolicy>;
00569 template class ScopeInfo<PreallocatedStorage>;
00570
00571 } }